1. 什么是反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
.java文件经过虚拟机编译成.class文件,也叫字节码文件。
Java在将.class字节码文件载入时,JVM将产生一个java.lang.Class对象代表该.class字节码文件,从该Class对象中可以获得类的许多基本信息,这就是反射机制。
反射就是类在运行期间,把类中成员抽取为其它类的过程。
反射的机制如下图所示:
Student.java经过了jdk的哪些过程?
Student.java-----javac-----Student.class(字节码文件)-----java命令-----可执行文件
其中,类加载器ClassLoader加载字节码文件到内存中,加载完毕后,在JVM中以Class的形式存在。
2. 为什么使用反射
反射是为了解决在运行期,对某个实例一无所知的情况下,如何调用其方法或属性。
例: spring框架中只需要传入类的路径----spring框架就会帮你创建类的对象。
3. 获取Class反射类的方式
获取class反射类有三种方式:
第一种:通过类名.class属性
// 第一种:通过类名.class属性获取反射类
Class<Student> class1 = Student.class;
第二种:通过类路径获取
// 第二种:通过类路径获取
Class class2 = Class.forName("com.fwx.entity.Student");
第三种:通过对象名获取反射类型
// 第三种:通过对象名获取反射类型
Student student = new Student();
Class class3 = student.getClass();
4. Class类中常用的方法
1.根据反射类得到实例对象 newInstance()
// 通过反射类创建类对象
Student student = class1.newInstance();
2.得到反射类上的注解对象。getAnnotation()
// 获取Student类上的注解
MyAnnotation annotation = class1.getAnnotation(MyAnnotation.class);
5. 获取Method方法类对象
获取Method方法类对象的方式有四种:
getDeclaredMethods(): 获取本类中所有的方法。
// 第一种:获取本类种所有的方法
Method[] declaredMethods = class1.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
getDeclaredMethod(“方法名”,参数类型):获取本类中指定的方法对象。
// 第二种:获取本类中指定的方法
Method studentShow01 = class1.getDeclaredMethod("studentShow01");
System.out.println(studentShow01);
getMethods():获取本类以及父辈类中public修饰的方法。
// 第三种:获取本类以及父类中的所有的public方法
Method[] methods = class1.getMethods();
for (Method method : methods) {
System.out.println(method);
}
getMethod(“方法名”,参数类型):获取本类以及父辈类中指定public修饰的方法。
// 第四种:获取本类以及父类中指定的public方法
Method studentShow02 = class1.getMethod("schoolShow01");
6. Method类对象中常用的方法
Object r=invoke(Object对象,参数值) 调用类中的方法
Student student = class1.newInstance();
Method printAge = class1.getDeclaredMethod("printAge", Integer.class);
// 调用获取的方法,传入相应的参数,返回方法返回的数据
Object invoke = printAge.invoke(student, 20);
setAccessible()设置允许访问私有成员
Method printAge02 = class1.getDeclaredMethod("printAge02", Integer.class);
printAge02.setAccessible(true); // 设置允许访问私有成员
Object invoke1 = printAge02.invoke(student, 18);
7. 获取Field属性对象的方式
获取Field属性对象的方式有四种,类似于获取Method方法类对象的方式:
getDeclaredFields(): 获取本类中所有的属性。
// 获取本类中所有的属性
Field[] declaredFields = class1.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
getDeclaredField(“属性名”):获取本类中指定的属性。
// 获取本类中指定的属性
Field name = class1.getDeclaredField("name");
System.out.println(name);
getFields():获取本类以及父辈类中public修饰的属性。
// 获取本类以及父辈类中public修饰的属性
Field[] fields = class1.getFields();
for (Field field : fields) {
System.out.println(field);
}
getField(“属性名”):获取本类以及父辈类中指定public修饰的属性。
// 获取本类以及父辈类中指定public修饰的属性
Field name1 = class1.getField("name");
8. Field类中常用的方法
set(Object对象,值):为属性赋值
// 通过类名.class属性获取反射类
Class<Student> class1 = Student.class;
Student student = class1.newInstance();
// 获取本类中指定的属性
Field name = class1.getDeclaredField("name");
name.setAccessible(true);
// 为属性赋值
name.set(student,"yzf");
getName():获取属性名
getAnnotation():获取属性上的注解对象
// 获取本类中所有的属性
Field[] declaredFields = class1.getDeclaredFields();
for (Field declaredField : declaredFields) {
// 获取属性名
String name1 = declaredField.getName();
// 获取属性上的注解对象
MyAnnotation annotation = declaredField.getAnnotation(MyAnnotation.class);
String value = annotation.value();
9. 通过读取properties属性文件,进行创建反射类,并进行相关操作
public static void main(String[] args) throws Exception{
// 加载数据文件
InputStream inputStream = ReflectionTest07.class.getClassLoader().getResourceAsStream("properties.properties");
Properties properties = new Properties();
properties.load(inputStream);
// 属性类读取属性文件中的key值
String className = properties.getProperty("ClassName");
// 根据类路径得到反射路径
Class<?> aClass = Class.forName(className);
// 根据反射路径得到反射对象
Object o = aClass.newInstance();
// 根据反射类创建类对象
Class<?> aClass1 = o.getClass();
// 获取对象中的所有属性
Field[] declaredFields = aClass1.getDeclaredFields();
// 遍历属性,进行相关操作
for (Field declaredField : declaredFields) {
// 相关操作代码
System.out.println(declaredField.getName());
}
}
可以得知,反射是在运行时,对原来类一无所知的情况下执行