2010-02-06 97 views
8

我想明白为什么下面不工作:动态实例创建没有泛型

public class HelloClass { 

    private class MyClass 
    { 
     public MyClass() 
     { 
      System.out.println ("Oh heck this is me!"); 
     } 
    } 

    public Object newInstance (Object o) 
    { 
     try { 
      // java.lang.InstantiationException here 
      return o.getClass().newInstance();   
     } catch (Exception e) { 
      e.printStackTrace(System.out); 
      return null; 
     } 
    } 

    public void run() 
    { 
     MyClass m = new MyClass(); 
     Object o = newInstance(m); 
    } 

    public static void main(String[] args) 
    { 
     HelloClass hd = new HelloClass(); 
     hd.run(); 
    } 
} 

我知道正确的方式通过声明的newInstance参数作为< T级>实现这一目标,但会想了解为什么不能像上面那样做。

UPD:这是我收到的例外:

java.lang.InstantiationException: HelloClass$MyClass 
    at java.lang.Class.newInstance0(Class.java:340) 
    at java.lang.Class.newInstance(Class.java:308) 
    at HelloClass.newInstance(HelloClass.java:14) 
    at HelloClass.run(HelloClass.java:24) 
    at HelloClass.main(HelloClass.java:30) 
+0

什么类,你试图实例?如果它是一个抽象类或接口,那么这将不起作用,你会得到一个InstantiationException。也许包括异常的堆栈跟踪会有所帮助。 – JasCav 2010-02-06 18:25:52

+0

我想实例化MyClass,认为它很明显,因为我调用newInstance(m),其中m是MyClass的一个实例;)。向原始帖子添加了例外。 – azerole 2010-02-06 18:28:56

+0

为什么在标题中提及泛型?他们与这个问题有什么关系? – skaffman 2010-02-06 18:40:18

回答

6

内部类的构造函数有一个隐藏的第一个参数,当您使用反射时需要提供。传递外部类的一个实例。

而不是

return o.getClass().newInstance(); 

使用:

return o.getClass().getConstructor(getClass()).newInstance(this); 
+0

而作为指定一个特定的构造函数的位置不是很健壮我想我现在明白为什么FindBugs在这种情况下抱怨该类应该是一个*静态*内部类。有趣! – 2010-02-06 18:40:03

+0

非常感谢。现在我明白了。 – azerole 2010-02-06 18:57:05

+0

哦,是的,这样很不错。 – 2010-02-06 19:02:27

1

的问题似乎是,这是一个非静态成员类,因为它是双向如果你声明MyClass为静态,如果你做它是一个顶级的课程。虽然不太清楚为什么。

1

非常好的问题!

这是因为内部类在每个构造函数中都有一个隐式参数 - 它的外部类。因此它没有默认的构造函数。

要获得它的一个实例,必须通过传递外部类作为参数来实例化它。

Constructor constructor = o.getClass().getConstructor(HelloClass.class); 
return constructor.newInstance(this); 
+0

这就是我的想法,但似乎'newInstance()'没有一个带有封闭对象的版本,你需要使用'Constructor'对象。 – skaffman 2010-02-06 18:35:24

+0

这就是我刚刚看到的:)修复它。 – Bozho 2010-02-06 18:37:16

+0

假设你的意思是'HelloClass.class',这对我来说不起作用,但会抛出'IllegalArgumentException':*错误的参数个数*。 – 2010-02-06 18:48:15

0

Class对象中的newInstance方法仅适用于具有无参数构造函数的具体类。

如果您将MyClass更改为静态,它将符合条件并且代码可以工作。事实上,它有一个隐含的构造函数,其外部对象作为参数,并且没有无参数构造函数。

您可以通过使用构造的newInstance方法使自己的newInstance方法工作:

public Object newInstance (Object o) 
{ 
    try { 
     final Constructor<? extends Object> constructor = 
        o.getClass().getConstructor(this.getClass()); 
     return constructor.newInstance(this); 
    } catch (Exception e) { 
     e.printStackTrace(System.out); 
     return null; 
    } 
} 
+0

只有在发布后,我才刷新并看到其他人给出了基本相同的答案。无论如何我会离开它,但感觉有点傻! – 2010-02-06 19:33:57