反射
反射的好处:在程序运行过程中操作对象
可以提高程序的扩展性,解耦
获取Class对象的时机方式:
1. .class文件未加载阶段
在未加载阶段,将字节码文件加载进内存,返回Class对象:Class.forName(“包名+类名”)
- 多用于配置文件,将类名定义在配置文件中,读取文件,加载类
1
2
3Class<?> clas1 = Class.forName("com.learn.reflect.Scholar");
System.out.println(clas1);
//class com.learn.reflect.Scholar
2. Class类对象阶段(对象已经被ClassLoader加载入内存),通过类名的属性:类名.class
- 多用于参数的传递
1
2
3Class<Scholar> clas2 = Scholar.class;
System.out.println(clas2);
//class com.learn.reflect.Scholar
3. 在程序Runtime阶段,使用Object类的方法:对象.getClass()
- 多用于对象获取字节码的方式
1
2
3
4Scholar scholar1 = new Scholar();
Class<? extends Scholar> clas3 = scholar1.getClass();
System.out.println(clas3);
//class com.learn.reflect.Scholar
比较三种方式
内存地址的比较1
2
3System.out.println(clas1 == clas2);//true
System.out.println(clas2 == clas3);//true
System.out.println(clas1 == clas3);//true
结论:不管用哪种方式获取的class对象是同一个,区别仅仅是获取的时机不同。
Class对象的操作
1.获取成员变量
- Field[] getFields() 获取public修饰的成员变量
Field getField(String name) 获取指定名字的public修饰的成员变量
Field[] getDeclaredFields() 获取所有定义了的成员变量
- Field getDeclaredFields(String name)
获取构造方法
- Constructor<?> [] getConstructors()
- Constructor
getConstructor(类<?>… parameterTypes) - Constructor<?> [] getDeclaredConstructors()
- Constructor
getDeclaredConstructor(类<?>… parameterTypes)
获取成员方法
- Method[] getMethods()
Method getMethod(String name, 类<?>… parameterTypes)
Method[] getDeclaredMethods()
- Method getDeclaredMethod(String name, 类<?>… parameterTypes)
获取类名
- String getName()
获取后的操作set() get()方法
1 | Scholar scholar = new Scholar(); |
类<?>… parameterTypes的含义
1 | Class<Scholar> clas2 = Scholar.class; |
getMehod如何执行
如果使用getMethods 返回的方法包含了Object的方法,因为所有类都是Object的子类
直接引用上一个代码块的Scholar对象obj1
2
3Method setAge = clas2.getMethod("setAge",int.class);
setAge.invoke(obj,50);
System.out.println(obj);
配置文件作为中间数据,加载执行其他类对象、方法
1 | Properties properties = new Properties(); |