我在玩匿名子类,发现一个无法解决的问题。
编辑:由于托马斯,问题得以解决,完整的工作代码在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类是FooTest $ 1,此类似乎没有扩展Foo
如果(1)是true,为什么可以使用FooTest $ 1设置“ Class c = [...]”
如果(1)为假而(2)正确工作,为什么找不到方法?
最佳答案
改为1):f2
的类型为FooTest$1
,它扩展了Foo
,但未打印出来,您只获得当前类,没有超类或接口。
至2):由于1)为假,因此这里没有问题:)
到3):问题在于,匿名内部类FooTest$1
需要创建外部FooTest
实例。通过反射调用构造函数将尝试创建没有FooTest
封闭实例的新实例,并且这样的方法不可用(即,创建内部类的实例而没有封闭类的实例的方法)。
您需要做的是获取将封闭类的实例作为其参数的构造函数。有关更多信息,请查看以下问题:Is it possible to create an instance of nested class using Java Reflection?
编辑:
我再次阅读您的代码,感到as愧,我错过了这一点:FooTest$1
类实际上是一个静态内部类,因为它是在静态main方法中创建的。因此,它没有构造函数接受封闭的类实例。
但是,由于您创建了类及其内联的构造函数,因此该构造函数不是公开可见的。因此,getClass().getConstructor()
不会返回它(此类仅返回公共构造函数。在这种情况下,您必须使用getClass().getDeclaredConstructor()
。对于字段和方法,仅对于记录而言,情况也是如此。