是否可以使用反射实例化一个匿名Java类。 我创建了一个匿名类,稍后我想再次实例化它,是否可以这样做? 我可以使用一个内部类来做到这一点,但是我真的需要使用一个匿名类吗?
答案 0 :(得分:3)
该语言的设计说明:不,匿名类不能实例化,除非在您使用过的那个地方。
在实践中:是的,您可以,但是,因为规范并未说明您可以这样做(实际上,该规范建议您不能但不保证不能这样做),无论您编写要做什么这可能(并且可能会!)在更高版本的Java中中断。当然,生成的类文件(这是一个更新的VM / classfile概念)将是其他文件的嵌套,并且模块系统会带来更严格的限制。
关于生成的类的实际名称,您也会在黑暗中陷入困境。
换句话说,“在您停止询问方式之前,也许您应该考虑一下原因”,然后重新考虑,因为不是这样。如果您以后需要再次使用它,请给它命名。那就是名字的意思。
所以,概念证明-但是不要这样做,这很愚蠢,会弹出,中止:
class Test {
public static void main(String[] args) throws Exception {
Runnable r = new Runnable() { public void run() {
System.out.println("Hello!");
}};
r.run();
Class<?> c = Class.forName("Test$1");
Object o = c.getDeclaredConstructor().newInstance();
((Runnable) o).run();
}
}
以上内容实际上适用于我的特定版本的Java,我的体系结构以及月球的当前阶段。明天可能不工作。还要注意,这样的事情的构造函数可能令人惊讶:例如,在这种情况下,匿名内部类是在静态方法内部进行的,因此没有“ this”自变量(通常将实例传递)。 Java是否会意识到您不使用匿名类中的Test.this
中的任何内容,因此是否忽略内部类中的取决于Java。您可以通过查询所有构造函数(.getDeclaredConstructors()
)来解决此问题,但是为什么要编写大量非常棘手且易于出错的代码,只是为了破解明天可能会失败的东西?
请。不要。
答案 1 :(得分:0)
我想你可以。使用标准反射
class Test {
public static void main(String[] args) throws Exception {
Runnable r = new Runnable() { public void run() {
System.out.println("Hello!");
}};
Class<?> clazz = r.getClass();
Object instance = clazz.newInstance();
System.out.println(instance); // Test$1@7c16905e
System.out.println(instance == r); // false
Method method = clazz.getMethod("run");
method.invoke(instance); // Hello!
}
}
假设我们定义了一个匿名类,但是没有将其实例保存到r
。然后我们可以使用Spoon
src / main / java / Test.java
import spoon.Launcher;
import spoon.reflect.CtModel;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtType;
import spoon.reflect.visitor.Filter;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception {
new Runnable() {
public void run() {
System.out.println("Hello!");
}
};
Launcher launcher = new Launcher();
launcher.addInputResource("src/main/java/Test.java");
CtModel model = launcher.buildModel();
Class<?> clazz = model
.getElements((Filter<CtClass<?>>) CtClass::isAnonymous)
.stream()
.map(CtType::getActualClass)
.findFirst().get();
Object instance = clazz.newInstance();
System.out.println(instance); //Test$1@3fb1549b
Method method = clazz.getMethod("run");
method.invoke(instance); // Hello!
}
}
pom.xml
<dependency>
<groupId>fr.inria.gforge.spoon</groupId>
<artifactId>spoon-core</artifactId>
<version>8.2.0</version>
</dependency>