[英]Instantiate an anonymous Java class using reflection
是否可以使用反射實例化匿名 Java 類。 我創建了一個匿名類,我想稍后再次實例化,無論如何要這樣做嗎? 我可以用內部類來做,但我真的需要用匿名類來做嗎?
該語言的設計說:不,匿名類不能被實例化,除非在你使用它的地方。
在實踐中:是的,你可以,但是,因為規范沒有說你可以(事實上,規范表明你不能但不承諾你不能),無論你寫什么來做到這一點,都可能(並且可能會!)在更高版本的 java 中中斷。 當然生成的類文件(這是一個較新的VM/類文件概念)是其他類文件的嵌套,並且模塊系統帶來了更嚴重的限制。
對於生成的類的實際名稱,您還會在黑暗中進行瘋狂的嘗試。
換句話說,“在你停下來問怎么做之前,也許你應該考慮一下為什么”,然后重新考慮,因為事實並非如此。 如果您以后需要再次使用它,請為該事物命名。 這就是名字的用途。
所以,概念證明 - 但不要這樣做,這是愚蠢的,彈出,中止:
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()
)來解決這個問題,但是為什么要編寫大量極其棘手且容易出錯的代碼來解決明天可能會失敗的問題?
請。 別。
我想你可以。 使用標准反射
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
。 然后我們可以使用勺子
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>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.