深入理解Java反射机制
java反射是java语言中一个强大而灵活的特性,它允许程序在运行时检查和操作类、接口、字段和方法。
为了方便理解下文,我先给出Cat对象
public class Cat implements jump,Run {private int age;public String name;protected String color;double height;Cat(String color){this.color=color;}public Cat(int age, String name, String color, double height) {super();this.age = age;this.name = name;this.color = color;this.height = height;}public void run(String name) {System.out.print("小猫的名字"+name);}private int setAge(int age) {return age;}void fly() {System.out.println("猫不会飞");}
}
什么是反射?
直观理解是:反射式获取类信息的一种能力
而什么又是类信息呢?可以大致概括为:方法/变量,构造器/继承和实现类或接口
反射基础:获取class对象
要使用反射,首先需要获取目标类的class对象。常见的方式:
// 1. 通过对象实例的getClass()方法
Cat cat = new Cat("black");
Class class1 = cat.getClass();// 2. 通过类字面常量.class语法
Class class2 = Cat.class;// 3. 通过Class.forName()方法
Class class3 = Class.forName("com.qcby.反射.Cat");// 这三种方式获取的Class对象是相同的
System.out.println(class1 == class2); // true
System.out.println(class2 == class3); // true
获取构造方法
通过Class对象可以获取类的构造方法:
Class clazz = Class.forName("com.qcby.反射.Cat");
// 获取所有声明的构造方法(包括非public的)
Constructor[] constructors = clazz.getDeclaredConstructors();
System.out.println(Arrays.toString(constructors));// 获取所有public构造方法
Constructor[] publicConstructors = clazz.getConstructors();
System.out.println(Arrays.toString(publicConstructors));// 获取特定参数的构造方法
Constructor specificConstructor = clazz.getDeclaredConstructor(String.class);
System.out.println(specificConstructor);
获取接口信息:
反射也可以获取类实现的接口:
Class clazz = Class.forName("com.qcby.反射.Cat");Class[] interfaces = clazz.getInterfaces();System.out.println(Arrays.toString(interfaces));
获取字段方法:
Class clazz = Class.forName("com.qcby.反射.Cat");// 获取字段
Field[] fields = clazz.getDeclaredFields();// 获取方法
Method[] methods = clazz.getDeclaredMethods();
declared与非declared方法的区别
方法类型 | 包含范围 | 访问权限限制 |
---|---|---|
getField()/getMethod() | 仅返回public成员(包括继承的) | 不包含非public成员 |
getDeclaredField()/ | 返回本类声明的所有成员 | 包含private/protected成员 |
getDeclaredMethod() | (不包括继承的) | 需要setAccessible(true) |
方法签名的精确匹配
// Cat类中的方法定义
public void run(String name) {...}
private int setAge(int age) {...}// 正确获取方式
Method runMethod = catClass.getMethod("run", String.class);
Method setAgeMethod = catClass.getDeclaredMethod("setAge", int.class);// 错误示例(会抛出NoSuchMethodException)
Method wrongMethod1 = catClass.getMethod("run"); // 缺少参数
Method wrongMethod2 = catClass.getMethod("setAge", int.class); // 忽略private限制
最后我给你一张图,可以清晰的看到获取Class对象是如何获取的