Java反射

简介

Java反射是在运行时动态获取类的信息并操作类的属性、方法和构造器的能力。

主要特点:

  1. 在运行时获取类的完整信息
  2. 可以动态创建对象、调用方法、访问字段
  3. 可以访问 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, "骨头");
}
相关推荐
资生算法程序员_畅想家_剑魔2 小时前
Java常见技术分享-分布式篇-分布式系统基础理论
java·开发语言·分布式
色空大师3 小时前
【Result<T>泛型接收转化失败】
java·泛型
Geoking.3 小时前
【设计模式】中介者模式(Mediator)详解
java·设计模式·中介者模式
大猫和小黄3 小时前
Java异常处理:从基础到SpringBoot实战解析
java·开发语言·spring boot·异常
hero.fei3 小时前
kaptcha 验证码生成工具在springboot中集成
java·spring boot·后端
mikelv013 小时前
实现返回树状结构小记
java·数据结构
Duang007_3 小时前
【LeetCodeHot100 超详细Agent启发版本】两数之和 (Two Sum)
java·人工智能·python
色空大师3 小时前
maven引入其他项目依赖爆红
java·maven
yangminlei4 小时前
深入理解Sentinel:分布式系统的流量守卫者
java