2012-01-19 16 views
2

私は匿名のサブクラスで遊んでいましたが、私が逃げることができない問題を発見しました。匿名サブクラス内のJava汎用オブジェクトの構築

EDIT:問題トーマスのおかげで解決され、完全な作業コードをペーストビン(Foo.java; FooTest.java)にある

2クラス。 fooとFooTest ... コード最初:

class Foo { 

    public Foo() {} 

    public void whichClassAmI() { 
     System.out.println(this.getClass());             
    } 

    public void say() { 
     System.out.println("Foo says: nothing");            
    } 

    public <T extends Foo> T getAnotherFoo() {            

     try {                     
      Class<? extends Foo> c = this.getClass();           
      T r = (T)(c.getConstructor().newInstance());          
      return r;                   
     } catch (Exception e) {                
      throw new RuntimeException(e);             
     } 
    }                       

} 

_

class FooTest {                    

    public static String stuff = "";               

    public static void main (String[] args) {             

     Foo f1 = new Foo();                 

     // instance of anon subclass               
     Foo f2 = new Foo(){                 
      public void say() {                
       System.out.println("Modded Foo says: " + stuff);        
      }                     
     };                     

     f1.whichClassAmI();                 
     f2.whichClassAmI();                 

     stuff = "stuff";                  
     f1.say();                    
     f2.say();                    

     Foo f3 = f1.getAnotherFoo();               
     f3.say();                    

     Foo f4 = f2.getAnotherFoo(); // <-- exception here 
    } 

} 

ので、このコードは、危険な動作の警告でコンパイルが実行され、例外がスローされます。出力は次のとおりです。

Note: Foo.java uses unchecked or unsafe operations. 
Note: Recompile with -Xlint:unchecked for details. 
class Foo 
class FooTest$1 
Foo says: nothing 
Modded Foo says: stuff 
Foo says: nothing 
Exception in thread "main" java.lang.RuntimeException: java.lang.NoSuchMethodException: FooTest$1.<init>() 
    at Foo.getAnotherFoo(Foo.java:20) 
    at FooTest.main(FooTest.java:23) 
Caused by: java.lang.NoSuchMethodException: FooTest$1.<init>() 
    at java.lang.Class.getConstructor0(Class.java:2723) 
    at java.lang.Class.getConstructor(Class.java:1674) 
    at Foo.getAnotherFoo(Foo.java:17) 
    ... 1 more 

私は理解していないことである。

  1. F2クラスがFooTest $ 1であり、このクラスには、(1)trueの場合はFoo

  2. を延長しないことのようですFooTestで$ 1

  3. (1)が偽で、(2)が正しく動作すると、なぜ "Class c = [...]"が設定できるのですか?

    1へ

答えて

4

):f2Fooを拡張するが、それが印刷されていない、あなただけの現在のクラスを取得していないし、何のスーパークラスやインターフェイスタイプFooTest$1です。 2へ

):1)が偽であるので、ここではそこに質問していない:)

)3:問題は、外部FooTestインスタンスを必要とFooTest$1 Annonymousの内部クラスを作成するということです。リフレクションを介してコンストラクタを呼び出すと、新しいインスタンスが作成され、FooTestのインスタンスがなくなり、そのようなメソッドは使用できません。つまり、内部クラスのインスタンスを作成するメソッドです。

あなたがする必要があることは、そのパラメータとして囲むクラスのインスタンスを取るコンストラクタを取得することです。 Is it possible to create an instance of nested class using Java Reflection?

編集

私はあなたのコードをもう一度読んで、私はこれを逃した恥ずかしい:FooTest$1クラスはそれがで作成されているので、実際に静的な内部クラスです詳細については、この質問を見て静的メインメソッド。このため、クラスインスタンスを囲むコンストラクタはありません。

ただし、クラスとそのコンストラクタをインラインで作成するため、そのコンストラクタは公開されていません。したがって、getClass().getConstructor()は返されません(このクラスではpublicコンストラクタが返されます)。その場合はgetClass().getDeclaredConstructor()を使用する必要があります。フィールドとメソッドについては、レコードの場合と同じです。

+0

私が指摘したリンクを読んでいますしかし、私はこれを私のanonサブクラスに適応させる方法を理解していません。getDeclaredClasses doenstはどのクラスも返します(サブクラスを宣言していないので明白です)。また、私はあなたに "Foo。(Foo)"というjava.lang.NoSuchMethodException:Fooクラスのコンストラクタに外部インスタンスを取得しようとしたときの方法を変更しました。そのコンストラクタを作成すると、もう一度古い例外です。 – cdx

+0

@cdxよく、 'c.getConstructor(FooTest.class).newInstance(someFooTestInstance)'のようなものを試してください。これは 'FooTest $ 1'インスタンスを作成し、' FooTest'にアクセスする場合にのみ機能します。囲むクラスを取得するには 'getClass()。getEnclosingClass()'を実行してください。 – Thomas

+0

@cdxコメントへのあなたの追加について:外側のクラスは 'Foo'(スーパークラス)ではなく' FooTest'です。 – Thomas

関連する問題