問:如下代碼段,已獲取外部類實例情況下,如何反射實例化內(nèi)部類及調(diào)用內(nèi)部類方法?
class OuterClass {
public void func(){
System.out.println("Outer class.");
}
class InnerClass {
private String mName;
public InnerClass(String name) {
mName = name;
}
void getName(){
System.out.println("name is:"+mName);
}
}
}
答:答案完整代碼如下:
class OuterClass {
public void func() {
System.out.println("Outer class.");
}
class InnerClass {
private String mName;
public InnerClass(String name) {
mName = name;
}
void getName() {
System.out.println("name is:"+mName);
}
}
}
public class Demo {
public static void main(String[] args) throws Exception {
Class outerClass = Class.forName("OuterClass");
//通過外部類的方法名獲取外部類的方法
Method method = outerClass.getDeclaredMethod("func");
//調(diào)用外部類實例的func方法,invoke第一參數(shù)為外部類實例
method.invoke(outerClass.newInstance());
//內(nèi)部類反射名字需要使用$分隔,編譯后生成的規(guī)則
Class innerClass = Class.forName("OuterClass$InnerClass");
//通過內(nèi)部類的方法名獲取內(nèi)部類的方法
Method method2 = innerClass.getDeclaredMethod("getName");
//特別注意!內(nèi)部類newInstance的第一個參數(shù)必須是外部類實例的引用
method2.invoke(innerClass.getDeclaredConstructors()[0].newInstance(outerClass.newInstance(),"yan"));
}
}
即便上面 InnerClass 的修飾符是 private,上面的代碼依舊可以成功反射,只是不能直接通過
outClass.new InnerClass("yan");
的方式去實例化內(nèi)部類。
但是,當上面 InnerClass 的修飾符如果是 static,即內(nèi)部類是靜態(tài)內(nèi)部類時,上面的代碼就不能用了,需要將答案的最后一行代碼改成
method2.invoke(innerClass.getDeclaredConstructors()[0].newInstance("yan"));
才行,因為靜態(tài)內(nèi)部類沒有持有外部類的任何引用,所以不用傳遞外部類實例對象的引用。
問:如何反射如下類的匿名內(nèi)部成員類?
class OuterClass {
public Runnable runnable = new Runnable() {
public void run() {
System.out.println("runnable.");
}
};
}
答:這種場景你就不要把它想成匿名內(nèi)部類了,直接當作外部類的成員變量去反射即可,如下。
class OuterClass {
public Runnable runnable = new Runnable() {
public void run() {
System.out.println("runnable.");
}
};
}
public class Demo {
public static void main(String[] args) throws Exception {
Class outerClass = Class.forName("OuterClass");
Runnable runnable = (Runnable) (outerClass.getField("runnable").get(outerClass.newInstance()));
runnable.run();
}
}