反射

1. 类加载器:

类的加载、类的连接、类的初始化

类的初始化:

  • 假如该类还未被加载和连接,程序先加载并连接该类
  • 假如该类的直接父类还未被初始化,先初始化其父类(初始化父类时也遵循这三个步骤)
  • 假如类有初始化语句,系统依次执行这些初始化语句

类加载器:将.class文件加载到内存中 -- ClassLoader

  • Bootstrap
  • Platform class loader
  • System class loader

2. 反射:

Java反射机制:指运行时获取一个类的变量和方法信息,通过获取的信息创建对象,调用方法的一种机制。增强程序灵活性,可以扩展

class类的对象

获取字节码文件对象:类.getClass、对象.getClass、forName

获取构造方法并创建对象

// 反射获取一个类的字节码文件
Class<?> c = Class.forName("com.itheima.Student");

// 获得多个(公共、所有)构造方法
Constructor<?>[] cons = c.getConstructors();
Constructor<?>[] dcons = c.getDeclaredConstructors();

// 获得单个构造方法
Constructor<Student> con = c.getConstructor();  // 无参构造
Constructor<Student> con = c.getConstructor(String.class, int.class, String.class);  // 带参构造

// 根据构造方法创建单个对象
Student s = con.newInstance();

// 此处可能出现创建对象的构造方法是私有的,需要使用暴力反射方法创建
con.setAccessible(true)

获取成员变量并使用

Class<?> c = Class.forName("com.itheima.Student");
Constructor<?> con = c.getDeclaredConstructor();
Object o = con.newInstance();

// 获得成员变量
Field addressField = c.getDeclaredField("address");
addressField.setAccessible(true);
// 通过成员变量的set方法给对象中的成员赋值
addressField.set(o, "西安");

获取成员方法并使用

Class<?> c = Class.forName("com.itheima.Student");
Constructor<?> con = c.getDeclaredConstructor();
Object o = con.newInstance();

// 获取成员方法
// 这里两个方法之间区别不仅是公共和私有,getMethods会获取本类及超类所有公共方法,getDeclaredMethod只有本类所有方法
Method[] Methods = c.getMethods();
Method[] DeclaredMethods = c.getDeclaredMethods();

Method dMethod = c.getDeclaredMethod();
dMethod.setAccessible(true);
// 调用方法
dMethod.invoke(o, "用到的参数");

反射 - 运行配置文件指定内容

Properties prop = new Properties();
FileReader fr = new FileReader("com/itheima/class.txt");
prop.load(fr);
fr.close();

String className = prop.getProperty("className");
String methodName = prop.getProperty("methodName");

Class<?> c = Class.forName(className);
Constructor<?> dcon = c.getDeclaredConstructor();
dcon.setAccessible(true);
Object o = dcon.newInstance();

Method dMethod = c.getDeclaredMethod(methodName);
dMethod.setAccessible(true);
dMethod.invoke(o);