学习Java的同学,反射是一个熟悉又陌生的概念,熟悉是知道反射是Java的一种机制,面试也会经常碰到,说陌生是平常很少用到。今天我带大家来认识一下Java的反射。
Java的正射vs反射
了解反射前,先让我思考下什么是Java的正射。在正常编写代码时,我们先定义一个类,比如程序员这个类,我们很轻松知道它有什么属性与方法。我们可以很轻松定义出对象进行方法调用,这就是正射。
public class 程序员 {
private String 编程语言;
private Boolean 社畜=true;
public String 加班(String result){
return result;
}
public static void main(String[] args) {
new 程序员("Java").加班("猝死");
new 程序员("H5").加班("秃头");
}
}
接下来,让我们看下反射,你们部门老大说,今天我们入职了几个新人,里面既有开发、也有测试(我们中间有了一个叛徒)。这下完蛋,走来一个人(对象),你不知道他到底是程序员还是测试。这个时候我们用反射机制,给了自己一双X光眼睛,把对着你走过来的人从头到脚都扫描一遍,你就能分辨出哪个是测试。
Class clazz=入职新人.getClass();
for (Field field:clazz.getFields()){
System.out.println("字段名:"+field.getName());
}
for (Method method:clazz.getMethods()){
System.out.println("方法名:"+method.getName());
}
如何获取Class以及实例化
闲话扯完,让我们看获取class的几种方式
// 通过类名获取Class对象
Class clazz = Class.forName("com.example.MyClass");
// 通过对象获取Class对象
Class clazz = obj.getClass();
//通过.class获取对象
Class clazz=MyClass.class
获取Class对象的属性
//输出非私有的成员变量,数组,包含从父类继承的成员变量
Field[] fields = cls.getFields();
for (Field field : fields) {
//设置值
field.setAccessible(true);
field.set(cls, fieldValue);
System.out.println(field.getName());
}
//输出所有定义成员变量,数组,但是不包含从父类继承而来的成员变量
fields = cls.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName());
}
获取Class对象的方法
//获取类定义的所有的方法,数组, 但是不包含从父类继承而来的方法
for (Method method:clazz.getDeclaredMethods()){
System.out.println("方法名:"+method.getName());
}
//类所有的非私有方法,数组, 包含从父类继承而来的方法
for (Method method:clazz.getMethods()){
System.out.println("方法名:"+method.getName());
}
方法的调用
Method workMethod = obj.getDeclaredMethod("work");
workMethod.invoke(obj);
Method workMethod = obj.getMethod("work");
workMethod.invoke(obj);
实例化
//可以调用任意构造函数实例化
Object object=clazz.getConstructor().newInstance();
//只能调用默认的无参构造函数实例化
Object object=clazz.newInstance();