一、Java反射概念
在 Java 中的反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法,并且对于任意一个对象,都能够调用它的任意一个方法。
这种动态获取信息以及动态调用对象方法的功能称为 Java 语言的反射机制,很多优秀的开源框架都是通过反射完成的。
二、Java 反射 API
反射 API 用来生成 JVM 中的类、接口或则对象的信息。
Class
类:反射的核心类,可以获取类的属性,方法等信息。
Field
类:Java.lang.reflec
包中的类,表示类的成员变量,可以用来获取和设置类之中的属性
Method
类: Java.lang.reflec
包中的类,表示类的方法,它可以用来获取类中的方法信息或者执行方法。
Constructor
类: Java.lang.reflec
包中的类,表示类的构造方法。
2.1 获取 Class 对象的 3 种方法
- 调用某个对象的
getClass()
方法
Person p=new Person();
Class clazz=p.getClass();
- 调用某个类的
class 属性
来获取该类对应的 Class 对象
Class clazz=Person.class;
- 使用
Class
类中的forName()静态方法
(最安全/性能最好)
Class clazz=Class.forName("类的全路径"); (最常用)
当我们获得了想要操作的类的 Class 对象
后,可以通过 Class 类中的方法获取并查看该类中的方法
和属性
。
//当我们获得了想要操作的类的 Class 对象后,可以通过 Class 类中的方法获取并查看该类中的方法和属性。
//获取类的所有方法信息
Method[] methods = aClass3.getMethods();
for (Method method : methods) {
System.out.println("方法:"+method.getName()+"()");
}
// Method[] declaredMethods = aClass3.getDeclaredMethods();
// for (Method declaredMethod : declaredMethods) {
// System.out.println("声明的方法"+declaredMethod.toString());
// }
/**
*getFields() 获得某个类的所有的公共(public)的字段,包括父类中的字段。
*getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
*/
Field[] fields = aClass3.getFields();
for (Field field : fields) {
System.out.println("private字段:"+field.toString());
}
Field[] declaredFields = aClass3.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("类中所有声明的字段:"+declaredField);
}
Constructor<?>[] constructors = aClass3.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("构造函数:"+constructor.toString());
}
2.2 通过class对象创建对象实例
- 使用
Class
对象的newInstance()
方法; - 调用
Constructor
对象的newInstance()
//通过Class对象的newInstance方法创造实例对象
Student stu1 = (Student)aClass3.newInstance();
System.out.println(stu1);
//首先通过class对象获得一个构造方法,在通过构造方法创建实例对象
Constructor<?> constructor = aClass3.getConstructor(String.class,int.class);
Student stu2 = (Student)constructor.newInstance("北京大学",703);
System.out.println(stu2);
三、代码演示
@Data
public class Person {
private String name;
private String sex;
private Integer age;
}
@Data
public class Student extends Person {
private String schoolName;
private Integer score;
public String teacher;
public Student(){
System.out.println("Student无参构造");
}
public Student(String schoolName,int score){
this.schoolName = schoolName;
this.score = score;
System.out.println("Student有参构造");
}
}
完整代码
package com.lsh.reflectbylsh;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author :LiuShihao
* @date :Created in 2021/2/25 7:38 下午
* @desc : 学习Java反射机制
*/
public class ReflectDemo {
/**
* 获得class对象的三种形式:
* 1.调用某个对象的 getClass()方法
* 2.调用某个类的 class 属性来获取该类对应的 Class 对象
* 3.使用 Class 类中的 forName()静态方法(最安全/性能最好)
*/
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Student student = new Student();
Class<? extends Student> aClass1 = student.getClass();
Class<Student> aClass2 = Student.class;
Class<?> aClass3 = Class.forName("com.lsh.reflectbylsh.Student");
//当我们获得了想要操作的类的 Class 对象后,可以通过 Class 类中的方法获取并查看该类中的方法和属性。
//获取类的所有方法信息
Method[] methods = aClass3.getMethods();
for (Method method : methods) {
System.out.println("方法:"+method.getName()+"()");
}
// Method[] declaredMethods = aClass3.getDeclaredMethods();
// for (Method declaredMethod : declaredMethods) {
// System.out.println("声明的方法"+declaredMethod.toString());
// }
/**
*getFields() 获得某个类的所有的公共(public)的字段,包括父类中的字段。
* getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
*/
Field[] fields = aClass3.getFields();
for (Field field : fields) {
System.out.println("private字段:"+field.toString());
}
Field[] declaredFields = aClass3.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("类中所有声明的字段:"+declaredField);
}
Constructor<?>[] constructors = aClass3.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("构造函数:"+constructor.toString());
}
//通过Class对象的newInstance方法创造实例对象
Student stu1 = (Student)aClass3.newInstance();
System.out.println(stu1);
//首先通过class对象获得一个构造方法,在通过构造方法创建实例对象
Constructor<?> constructor = aClass3.getConstructor(String.class,int.class);
Student stu2 = (Student)constructor.newInstance("北京大学",703);
System.out.println(stu2);
}
}