前言
反射,是Java中一个特别重要的知识点,它把面向对象这一核心思想提升了一个档次,在反射中,出现了类对象(类的字节码文件对象),构造器对象,成员变量对象,成员方法对象等等
而关于反射的具体作用,对于我一个刚刚接触完反射的人来说,好像并没有什么太大的价值(毕竟这玩意无论是代码规模还是复杂度都比直接new一个对象麻烦不少,不过听说反射在框架什么的地方会有大用处,以后再说吧)
正文
反射可以通过类路径(方便我记忆,瞎编的名词)来获取对应类的字节码文件对象,这不禁让我产生了一个想法,如果我想通过反射获取内部类的字节码文件对象,应该怎么操作呢?
先复习一下内部类:,内部类是指定义在外部类内部的类,如果没有外部类对象的引用,其他地方将无法直接访问内部类
也就是说,即使是强大的反射,在没有外部类对象的指引,也无法直接访问内部类,即Class.forName()方法对于内部类将无法起作用,而其余两种方法,即 类名.Class和对象名.getClass()的前提都是要拥有对该类的访问权,这对于内部类依然无用
getClasses()和getDeclaredClasses(),应该注意的是这里的Class一定得是复数形式,因为getClass()的作用和它们完全不同.
同理,在创建内部类的构造器对象时也要在方法的参数中添加外部类的构造器对象,再根据基本规则创建。
如以下代码
//类代码
``````public class OutClass1 {
public OutClass1(){}
public static void getMessage(){
System.out.println("Out has run!");
}
public class InClass{//无论是public还是private,效果一致
public InClass() {}
public static void getMessage(){
System.out.println("In has run!");
}
//测试代码
```
ublic class ReflectDemoNo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<?> outClass = Class.forName("反射.内部类测试.OutClass1");
Class<?>inClass=outClass.getDeclaredClasses()[0];
Constructor<?> outCon = outClass.getConstructor();
Constructor<?> inCon = inClass.getDeclaredConstructor(outClass);
OutClass1 outObj = (OutClass1)outCon.newInstance();
Object inObj = inCon.newInstance(outObj);
Method outMessage = outClass.getMethod("getMessage");
outMessage.invoke(outObj);
Method inMessage = inClass.getMethod("getMessage");
inMessage.invoke(inObj);
}
}
其他情况
当内部类被static修饰时,就只在创建内部类字节码文件对象时需要外部类的字节码文件对象去寻找内部类,其余操作与正常操作一致,这里就不多赘述,了解被静态修饰符修饰的东西的加载规则就很容易理解了。
总结
- 通过反射进行正常内部类的相关操作需要外部类的支持,但一旦内部类的构造器对象被创建,就不需要外部类了。
- 通过反射进行被static修饰的内部类的相关操作仅在获取字节码文件对象时需要外部类的辅助。
另外,fancy主题真好用,嘿嘿。