多用于框架和组件,写出复用性高的通用程序。
1. class类
获得class类的三种方法
(1)已知类–类名.class
(2)已知对象–对象.getClass()
(3)完整类名 String格式–Class.forName(完整类名) 常用
public void demo1() throws ClassNotFoundException {
// 获得class对象的三种方式
// 1.已知类
Class c1 = ReflectTest.class;
// 2.已知对象
Object o = new ReflectTest();
Class c2 = o.getClass();
// 3.完整的类名String格式
String className = "Reflect.qddx.ReflectTest";
Class c3 = Class.forName(className);
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
}
- Constructor
通过字节码对象获得构造器 ,成员变量方法,有两种
(1)获得所有getConstructors()
(2)获得指定getConstructor()
通过 newInstance()获得对象
public void demo2() throws Exception {
// 获得 Person的字节码对象
String className = "Reflect.qddx.Person";
Class c = Class.forName(className);// c 就是 Person的字节码对象
// 通过字节码获得一个类的构造器
Constructor[] constructors = c.getConstructors();
System.out.println(constructors.length);
// 获得指定构造器
Constructor constructor1 = c.getConstructor();
// 获得String类型参数的构造器
Constructor constructor2 = c.getConstructor(String.class);
Person p1 = new Person();// 调用无参构造器
// 使用反射实现相同的效果
Object p2 = constructor1.newInstance();// 调用无参构造器 构造Person对象
Object p2_2 = c.newInstance();// 通过class对象newInstance调用目标类无参构造器
Person p3 = new Person("abcd");// 调用有参的构造器
// 使用反射调用String 参数构造器
Object p4 = constructor2.newInstance("abcd");// 与p3 等价
}
3.Field类
field对象的获得
(1)getFields()获得所有public 成员变量,包括父类继承。
(2)getDeclaredFields() 获得当前类定义所有成员–包括private
当需要获得指定成员时,上面的方法 传入参数即可。
操作private属性,将setAccessible(true)
public void demo3() throws Exception {
Person p = new Person("Linda");
// 获得Person的字节码对象
Class c = Class.forName("Reflect.qddx.Person");
// 操作成员变量实例 name 获得name代表field对象
Field[] f1 = c.getFields();
System.out.println(f1.length);
Field[] f2 = c.getDeclaredFields();
System.out.println(f2.length);
// 获得name 成员变量
Field field = c.getDeclaredField("name");
field.setAccessible(true);// 设置可以访问私有的成员变量
// 获得p对象指定的name值
Object value = field.get(p);// 等价于p.getName()
System.out.println(value);
// 修改p的值
field.set(p, "MerLin");
System.out.println(field.get(p));
}
- Method
getDeclaredMethods()获得所有当前类声明方法。
getDeclareMethod()获得指定方法。
通过Method类提供invoke()执行方法
public void demo4() throws Exception {
Person p = new Person();
// 调用 p 对象中setName 设置 name的值 mary
// 获得Person的字节码对象
Class c = Class.forName("Reflect.qddx.Person");
// 2.操作setName 获得setName 对应反射对象 Method对象
// String类型参数 setName方法
Method setName = c.getDeclaredMethod("setName", String.class);
// 调用p对象的setName
setName.invoke(p, "Melin");// p.setName("Merlin")
// 读取name值得getName方法
Method getName = c.getDeclaredMethod("getName");
Object name = getName.invoke(p);
System.out.println(name);
}
综合应用实例
public void demo5() throws Exception {
// 已知String完整类型名 获得字节码对象
String className = "Reflect.qddx.Person";
Class c = Class.forName(className);
// 已知class对象 构造实例
Object obj = c.newInstance();
// 获得字节码对象中指定的属性和方法
Field f = c.getDeclaredField("name");// 获得name属性
Method setName = c.getDeclaredMethod("setName", String.class);// 获得setName方法。
// 修改属性的值,执行相应的方法
f.setAccessible(true);
f.set(obj, "Mary");
setName.invoke(obj, "Linda");
// 以上代码等价于以下代码
Person p = new Person();
// p.name = "Mary";
p.setName("Linda");
}
案例 :晚会
工厂+反射+配置文件