2010-02-06 107 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