反射
反射(Reflection) 是计算机科学中的一个概念,特别在面向对象的编程语言和环境中,它允许程序在运行时(runtime)检查和修改其结构、行为或状态。反射主要提供了以下功能:
运行时类型信息:通过反射,程序可以获取关于类、接口、字段和方法的信息。
动态方法调用:程序可以在运行时调用任何对象的方法,即使该方法在编译时是不可知的。
动态创建和操作对象:通过反射,程序可以在运行时创建新的对象实例,并调用其方法或访问其字段。
反射在多种编程语言中都有实现,如Java、C#、Python等。但在某些语言中,如C++,反射的功能可能不那么直接或完整。
在Java中,反射的主要API位于java.lang.reflect包中,提供了如Class、Method、Field、Constructor等类来访问和修改运行时的类信息。
然而,反射虽然强大,但也应谨慎使用,因为它破坏了封装性,可能导致性能下降,并可能使代码更难以理解和维护。因此,在决定使用反射之前,应仔细权衡其利弊。
字节码对象获取Class
public void reflectionTest() throws Exception {
/*方法一
* 使用Class.forName()
* 最常用
* */
Class clazz1 = Class.forName("org.example.People");
System.out.println(clazz1);//class org.example.People
/*方法二
* 使用类名.class
* 一般当作参数使用
* */
Class clazz2 = People.class;
System.out.println(clazz2);//class org.example.People
/*方法三
* 使用对象.getClass()
* 有对象时才可以使用
* */
People people = new People();
Class clazz3 = people.getClass();
System.out.println(clazz3);//class org.example.People
/*比较获取的对象*/
System.out.println(clazz1==clazz2);//true
System.out.println(clazz1==clazz3);//true
/*三种方法获取的对象相同*/
}
获取构造方法Constructor
使用Class实例方法获取Class-API
public void reflectionReadConstructorT() throws Exception {
Class clazz = Class.forName("org.example.People");
/*通过clazz.getConstructors()获取所有公共public的构造方法*/
Constructor[] cs1 = clazz.getConstructors();
System.out.println("================getConstructors()======================");
Arrays.stream(cs1).forEach(System.out::println);
/*================getConstructors()====================== out
public org.example.People(java.lang.String)
public org.example.People()
public org.example.People(java.lang.String,int)*/
/*通过clazz.getConstructor(Class...)获取指定参数类型的public构造方法*/
Constructor constructor1 = clazz.getConstructor(String.class);//获取参数为String的public构造方法
System.out.println("================getConstructor()======================");
System.out.println(constructor1);
/*================getConstructor()======================
public org.example.People(java.lang.String)*/
/*通过clazz.getDeclaredConstructors()获取所有声明的构造方法*/
Constructor[] cs2 = clazz.getDeclaredConstructors();
System.out.println("================getDeclaredConstructors()======================");
Arrays.stream(cs2).forEach(System.out::println);
/*================getDeclaredConstructors()====================== out
public org.example.People(java.lang.String)
public org.example.People()
public org.example.People(java.lang.String,int)
private org.example.People(int)*/
/*通过clazz.getDeclaredConstructor(Class...)获取指定参数类型的所有访问类型的构造方法*/
Constructor constructor2 = clazz.getDeclaredConstructor(int.class);//获取参数为String的构造方法
System.out.println("================getDeclaredConstructor()======================");
System.out.println(constructor2);
/*================getDeclaredConstructor()======================
private org.example.People(int)*/
}
操作构造方法
使用Constructor实例方法操作Constructor-API
public void displayConstructorT() throws Exception {
Class clazz = Class.forName("org.example.People");
/*获取所有构造方法*/
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
/*获取修饰符*/
System.out.println("/*获取修饰符*/");
System.out.println(declaredConstructor.getModifiers());
/*获取参数个数*/
System.out.println("/*获取参数个数*/");
System.out.println(declaredConstructor.getParameterCount());
/*获取参数列表*/
System.out.println("/*获取参数列表*/");
Arrays.stream(declaredConstructor.getParameters()).forEach(System.out::println);
/*获取参数列表*/
System.out.println("/*获取参数列表*/");
Arrays.stream(declaredConstructor.getParameterTypes()).forEach(System.out::println);
}
/*操作构造方法
* 使用构造方法创建对象*/
System.out.println(declaredConstructors[0].newInstance());
System.out.println(declaredConstructors[3]);//私有构造方法
declaredConstructors[3].setAccessible(true); //直接调用会报错 //绕过权限访问
System.out.println(declaredConstructors[3].newInstance(10));
}
获取字段对象Field
使用Class实例方法获取Class-API
操作字段对象
使用Field实例方法操作字段对象Field-API
获取成员方法Method
使用Class实例方法获取Class-API
操作成员方法
使用Method实例方法操作Method-API