简介
Java反射是在运行时动态获取类的信息并操作类的属性、方法和构造器的能力。
主要特点:
- 在运行时获取类的完整信息
- 可以动态创建对象、调用方法、访问字段
- 可以访问 private 成员
反射的核心类:
- Class:代表类和接口
- Field:代表类的成员变量
- Method:代表类的方法
- Constructor:代表类的构造方法
基本使用
1.获取Class对象
java
// 方式1:通过类名.class
Class<String> stringClass = String.class;
// 方式2:通过对象.getClass()
String str = "hello";
Class<?> strClass = str.getClass();
// 方式3:通过Class.forName()
try {
Class<?> clazz = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
2.创建对象实例
构造器相关方法
| Class方法 | 说明 |
|---|---|
| getConstructors | 获取全部构造器(限制public修饰符) |
| getDeclaredConstructors | 获取全部构造器(不限制修饰符) |
| getConstructor(Class<?>... parameterTypes) | 获取某个构造器(限制public修饰符) |
| getDeclaredConstructor(Class<?>... parameterTypes) | 获取某个构造器(不限制修饰符) |
| Constructor方法 | 说明 |
|---|---|
| newInstance(Object ... initargs) | 调用构造器创建对象实例 |
| setAccessible(boolean flag) | 当 accessible 设置为 true 时会抑制 java 语言的访问控制检查 |
基本示例
java
// Dog.java
public class Dog {
public String name;
private int age;
public Dog() {
}
private Dog(String name, int age) {
this.name = name;
this.age = age;
}
public void show() {
System.out.println("汪汪汪");
}
private void eat(String name) {
System.out.println("今天吃:" + name);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
java
// ReflectDemo.java
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.example.Dog");
// 获取类的全类名
System.out.println(clazz.getName());
// 获取类名
System.out.println(clazz.getSimpleName());
// 获取所有构造方法
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
// 遍历构造方法
for (Constructor<?> constructor : constructors) {
System.out.println(constructor.getName() + "(" + constructor.getParameterCount() + ")");
}
// 获取无参构造器
Constructor<?> cons1 = clazz.getDeclaredConstructor();
Dog dog1 = (Dog) cons1.newInstance();
System.out.println(dog1);
// 获取有参构造器
Constructor<?> cons2 = clazz.getDeclaredConstructor(String.class, int.class);
// 允许访问 private 构造器
cons2.setAccessible(true);
Dog dog2 = (Dog) cons2.newInstance("旺财", 5);
System.out.println(dog2);
}
3.访问和修改成员变量
成员变量相关方法
| Class方法 | 说明 |
|---|---|
| getFields | 获取全部成员变量(限制public修饰符) |
| getDeclaredFields | 获取全部成员变量(不限制修饰符) |
| getField(String name) | 获取某个成员变量(限制public修饰符) |
| getDeclaredField(String name) | 获取某个成员变量(不限制修饰符) |
| Field方法 | 说明 |
|---|---|
| set(Object obj, Object value) | 赋值 |
| get(Object obj) | 取值 |
| setAccessible(boolean flag) | 当 accessible 设置为 true 时会抑制 java 语言的访问控制检查 |
基本示例
java
// ReflectDemo.java
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.example.Dog");
// 获取所有属性
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// 输出 属性名:属性类型
System.out.println(field.getName() + ":" + field.getType());
}
Dog dog = new Dog();
// 获取 name 属性
Field field1 = clazz.getDeclaredField("name");
// 设置属性值
field1.set(dog, "旺财");
System.out.println(field1.get(dog));
// 获取 age 属性
Field field2 = clazz.getDeclaredField("age");
// 忽略访问权限修饰符
field2.setAccessible(true);
field2.set(dog, 5);
System.out.println(field2.get(dog));
}
4.调用方法
成员方法相关方法
| Class方法 | 说明 |
|---|---|
| getMethods | 获取全部成员方法(限制public修饰符) |
| getDeclaredMethods | 获取全部成员方法(不限制修饰符) |
| getMethod(String name, Class<?>... parameterTypes) | 获取某个成员方法(限制public修饰符) |
| getDeclaredMethod(String name, Class<?>... parameterTypes) | 获取某个成员方法(不限制修饰符) |
| Method方法 | 说明 |
|---|---|
| invoke(Object obj, Object... args) | 调用某个对象的方法 |
| setAccessible(boolean flag) | 当 accessible 设置为 true 时会抑制 java 语言的访问控制检查 |
基本示例
java
// ReflectDemo.java
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.example.Dog");
Dog dog = new Dog();
// 获取所有方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName() + "(" + method.getParameterCount() + ")");
}
// 获取 show 方法
Method method = clazz.getDeclaredMethod("show");
// 调用方法
method.invoke(dog);
// 获取 eat 方法
Method eat = clazz.getDeclaredMethod("eat", String.class);
// 忽略访问权限修饰符
eat.setAccessible( true);
// 调用方法
eat.invoke(dog, "骨头");
}