匿名子类中的java泛型对象构造

时间:2012-01-19 13:48:13

标签: java generics inheritance

我正在玩匿名子类,我发现了一个我无法解决的问题。

编辑:问题解决了,感谢托马斯,完整的工作代码在pastebin上(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 class是FooTest $ 1,这个类似乎没有扩展Foo

  2. 如果(1)为真,为什么“C = [...]”可以用FooTest $ 1设置

  3. 如果(1)为假,(2)工作正常,为什么不找到方法?

1 个答案:

答案 0 :(得分:4)

To 1):f2的类型为FooTest$1,它扩展了Foo但是没有打印,你只需要获取当前的类,没有超类或接口。

To 2):因为1)是假的,所以这里没有问题:)

To 3):问题是匿名内部类FooTest$1需要创建一个外部FooTest实例。通过反射调用构造函数将尝试创建一个新的实例,而不用一个封闭的FooTest实例,并且这样的方法不可用(即一个创建内部类的实例的方法,而不是封闭类的实例)。

您需要做的是获取将封闭类的实例作为其参数的构造函数。有关详细信息,请查看此问题:Is it possible to create an instance of nested class using Java Reflection?

修改

我再次阅读你的代码而感到惭愧我错过了这个:FooTest$1类实际上是一个静态内部类,因为它是在静态main方法中创建的。因此,没有构造函数采用封闭的类实例。

但是,由于您创建了类及其构造函数,因此构造函数不是公开可见的。因此getClass().getConstructor()不会返回它(这个类只返回公共构造函数。在这种情况下,你必须使用getClass().getDeclaredConstructor()。字段和方法也是如此,只是为了记录。