目录
通过字节码对象获取Field、 Method和Constructor的方法:
这篇文章全属于我自己的看法呢,如果一小伙伴看到的话请批判性的来看,因为我们看法和表述不一定准确。
反射的定义
关于反射的定义这个问题,我刚开始是很懵的,因为我们平时接触到的定义往往都是什么是什么的格式来给出解释,但是我查了很多资料也没有查出有反射是什么这种句型的定义,这让我觉得反射是一个很深奥的东西,但是看了一些大神的解释之后我觉得反射在Java中就是一个具有上帝视角的工具。
下面是我查询到的反射的定义:
反射允许对成员变量,成员方法和构造方法的信息进行编程访问。
我的理解:
我觉得Java代码归根结底就是由一个个类组成的,而反射可以访问这些类中的信息,就包括类的属性(成员变量)、类的方法(成员方法)以及类的构造方法。而类就是由这些东西组成的,所以我说反射在Java中具有上帝视角,所有的类里面有些什么东西都能通过反射来看到。所有的类在反射面前都是透明的,即使是私有的属性或者方法也能通过反射访问到。
学习反射的要点:
学习反射最重要的就是通过反射来获取类中的属性、方法、构造方法等,并对它们进行剖析。但是我们从类中获取这些东西并不是直接在我们平时编写的代码中直接获取而是要通过字节码对象来获取,所以我们首先要学习获取字节码对象的三种方式:
//1、Class.forName(类的完整路径)
Class clazz1 = Class.forName("com.situ.reflect.Student");
//2、类型.class
Class clazz2 = Student.class;
//对象名.getClass
Student student = new Student();
Class clazz3 = student.getClass();
通过上面的代码可以看到获取的字节码对象都是Class类型,这就要说一下这个Class类了。
Class是反射的核心类
每个类加载到内存后,系统都会有唯一的一份字节码对象(比如Person.class/Student.class字节码对象都是Class这个类的实例)
就像是通过抽取Student类和Teacher类的共同特征我们可以抽取出一个Person类,Person类里面具有Teacher类和Student类的共同特征,我们把所有类的共同特征抽取出来就得到了Class类,那么所有的类的共同特征有哪些呢?
- 所有的类都有属性 Field
- 所有类都有方法 Method
- 所有类都有构造方法 Constructor
在Class中定义了获取Field、 Method和Constructor的方法,常用的有下面几个:
通过字节码对象获取Field、 Method和Constructor的方法:
这些方法都是通过字节码对象来调用的。
public void testConstructor() {
Class clazz = Student.class;
Constructor[] constructors = clazz.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
System.out.println(constructor.getName());//构造方法的名字
System.out.println(constructor.getModifiers());//修饰符
}
}
@Test
public void testConstructor2() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class clazz = Student.class;
//private Student(Integer id, String name, Integer age, String gender)
Constructor constructor = clazz.getDeclaredConstructor(Integer.class, String.class, Integer.class, String.class);
//在反射面前,私有的都可以访问
constructor.setAccessible(true);
//Student student = new Student(1, "zhansgan", 23, "男");
Student student = (Student) constructor.newInstance(1, "zhangsan", 23, "男");
System.out.println(student);
}
Student{id=1, name='zhangsan', age=23, gender='男'}
public void testMethod() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//Student student = new Student();
//student.setName("lisi");
Class clazz = Class.forName("com.situ.day15.Student");
//得到无参构造方法
Constructor constructor = clazz.getConstructor();
//调用newInstance实例化对象
Student student = (Student) constructor.newInstance();
//student.setName("lisi");
Method method = clazz.getMethod("setName", String.class);
method.invoke(student, "lisi");
System.out.println(student);
}
这就是Class类,以及通过Class类可以拿到的类的属性、方法、构造方法等。
那么同理,所有类的属性Field也具有共同特征:
- 修饰符; //private
- 类型; //String
- 变量名字; // name
这样我们通过上面的字节码对象拿到Field之后又可以通过Field来拿到类属性中的修饰符、类型、变量名等。
通过Method可以获得方法的名字、参数、返回值。
就这样我们就可以通过反射把一个类里面所有的东西都剖析出来了,所以类在反射面前是透明的。
总结
反射的核心类Class类
获取字节码对象的3种方式
1、Class.forName(类的完整路径) 2、类型.class 3、对象名.getClass
Class类具有属性Field、Method、Constructor,通过字节码对象来获得这些属性
Field类具有属性修饰符、类型、变量名字等
Method类具有属性返回值、参数、名字等
Constructor名字,声明的注解等