我正在玩匿名子类,我发现了一个我无法解决的问题。
编辑:问题解决了,感谢托马斯,完整的工作代码在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
我不明白的是:
f2 class是FooTest $ 1,这个类似乎没有扩展Foo
如果(1)为真,为什么“C = [...]”可以用FooTest $ 1设置
如果(1)为假,(2)工作正常,为什么不找到方法?
答案 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()
。字段和方法也是如此,只是为了记录。