java 反射

允许程序在运行时访问和操作类的属性和方法。这使得 Java 在某些情况下更加灵活,能够动态地加载类、创建对象以及调用方法。

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectionExample {

    public static void main(String[] args) throws Exception {
        // 获取 Class 对象
        Class<?> clazz = Class.forName("com.example.MyClass");

        // 创建实例
        Constructor<?> constructor = clazz.getConstructor();
        Object instance = constructor.newInstance();

        // 访问字段
        Field field = clazz.getDeclaredField("myField");
        field.setAccessible(true); // 访问私有字段
        field.set(instance, "Hello Reflection");

        // 调用方法
        Method method = clazz.getDeclaredMethod("myMethod");
        method.setAccessible(true); // 访问私有方法
        method.invoke(instance);
    }
}

1. 获取 Class 对象

  • Class.forName(String className):通过类名获取对应的 Class 对象。
  • MyClass.class:直接通过类名获取 Class 对象。
  • object.getClass():通过对象获取其对应的 Class 对象。
package com.example;

public class MyClass {
    private String message;

    public MyClass() {
        this.message = "Hello, World!";
    }

    public void displayMessage() {
        System.out.println(message);
    }
}
public class ReflectionExample {
    public static void main(String[] args) {
        try {
            // 1. 使用 Class.forName
            Class<?> clazz1 = Class.forName("com.example.MyClass");
            System.out.println("Class Name from forName: " + clazz1.getName());

            // 2. 使用 MyClass.class
            Class<MyClass> clazz2 = MyClass.class;
            System.out.println("Class Name from class literal: " + clazz2.getName());

            // 3. 使用 object.getClass()
            MyClass myObject = new MyClass();
            Class<?> clazz3 = myObject.getClass();
            System.out.println("Class Name from instance: " + clazz3.getName());

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}



//输出结果
Class Name from forName: com.example.MyClass
Class Name from class literal: com.example.MyClass
Class Name from instance: com.example.MyClass

2. 创建对象(调用构造器)

  • newInstance():通过无参构造器创建类的实例(已被弃用,推荐使用 Constructor)。
  • Constructor
    • getConstructor(Class<?>... parameterTypes):获取公共构造器。
    • getDeclaredConstructor(Class<?>... parameterTypes):获取声明的构造器(包括私有构造器)。
    • newInstance(Object... initargs):通过构造器创建实例。
package com.example;

public class Person {
    private String name;
    private int age;

    // 无参构造器
    public Person() {
        this.name = "Unknown";
        this.age = 0;
    }

    // 带参数的构造器
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 私有构造器
    private Person(String name) {
        this.name = name;
        this.age = 25; // 默认年龄
    }

    public void display() {
        System.out.println("Name: " + name + ", Age: " + age);
    }

    public static Person createWithName(String name) throws Exception {
        Constructor<?> privateConstructor =     
        Person.class.getDeclaredConstructor(String.class);
        privateConstructor.setAccessible(true); // 允许访问私有构造器
        return (Person) privateConstructor.newInstance(name);
    }

}
public class ReflectionExample {
    public static void main(String[] args) {
        try {
            // 1. 使用 newInstance()(已被弃用)
            Class<?> clazz = Class.forName("com.example.Person");
            Person person1 = (Person) clazz.newInstance();
            person1.display(); // 输出: Name: Unknown, Age: 0

            // 2. 获取公共构造器
            Constructor<?> publicConstructor = clazz.getConstructor(String.class, int.class);
            Person person2 = (Person) publicConstructor.newInstance("Alice", 30);
            person2.display(); // 输出: Name: Alice, Age: 30

            // 3. 通过私有构造器创建实例
            Person person3 = Person.createWithName("Bob");
            person3.display(); // 输出: Name: Bob, Age: 25

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3. 访问字段

  • getField(String name):获取公共字段。
  • getFields() :获得所有公共字段,返回Field[]数组。
  • getDeclaredField(String name):获取声明的字段(包括私有字段)。
  • getDeclaredFields():获得声明的所有字段(包括私有字段),返回Field[]数组。
  • Field 类的方法
    • get(Object obj):获取字段的值。
    • set(Object obj, Object value):设置字段的值。
    • setAccessible(true):允许访问私有字段。
package com.example;

public class Car {
    public String brand;
    private int year;

    public Car(String brand, int year) {
        this.brand = brand;
        this.year = year;
    }

    public void display() {
        System.out.println("Brand: " + brand + ", Year: " + year);
    }
}
import java.lang.reflect.Field;

public class ReflectionExample {
    public static void main(String[] args) {
        try {
            // 创建 Car 实例
            Car car = new Car("Toyota", 2020);

            // 1. 获取公共字段
            Field brandField = Car.class.getField("brand");
            String brandValue = (String) brandField.get(car);
            System.out.println("Brand: " + brandValue); // 输出: Brand: Toyota

            // 2. 获取私有字段
            Field yearField = Car.class.getDeclaredField("year");
            yearField.setAccessible(true); // 允许访问私有字段
            int yearValue = (int) yearField.get(car);
            System.out.println("Year: " + yearValue); // 输出: Year: 2020

            // 3. 修改公共字段
            brandField.set(car, "Honda");
            car.display(); // 输出: Brand: Honda, Year: 2020

            // 4. 修改私有字段
            yearField.set(car, 2022);
            car.display(); // 输出: Brand: Honda, Year: 2022

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


//输出
Brand: Toyota
Year: 2020
Brand: Honda, Year: 2020
Brand: Honda, Year: 2022

4. 调用方法

  • getMethod(String name, Class<?>... parameterTypes):获取公共方法。
  • getMethods():获取所有公共方法,返回Method[]数组。
  • getDeclaredMethod(String name, Class<?>... parameterTypes):获取声明的方法(包括私有方法)。
  • getDeclaredMethod():获取所有声明的方法(包括私有方法)。返回Method[]数组。
  • Method 类的方法
    • invoke(Object obj, Object... args):调用方法。
    • setAccessible(true):允许访问私有方法。
package com.example;

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }

    private int subtract(int a, int b) {
        return a - b;
    }

    public void displayResult(int result) {
        System.out.println("Result: " + result);
    }
}
import java.lang.reflect.Method;

public class ReflectionExample {
    public static void main(String[] args) {
        try {
            // 创建 Calculator 实例
            Calculator calculator = new Calculator();

            // 1. 获取所有公共方法
            Method[] publicMethods = Calculator.class.getMethods();
            System.out.println("Public Methods:");
            for (Method method : publicMethods) {
                System.out.println(method.getName());
            }

            // 2. 获取所有声明的方法(包括私有方法)
            Method[] allMethods = Calculator.class.getDeclaredMethods();
            System.out.println("\nAll Declared Methods:");
            for (Method method : allMethods) {
                System.out.println(method.getName());
            }

            // 3. 调用公共方法
            Method addMethod = Calculator.class.getMethod("add", int.class, int.class);
            int sum = (int) addMethod.invoke(calculator, 5, 3);
            System.out.println("\nSum: " + sum); // 输出: Sum: 8

            // 4. 调用私有方法
            Method subtractMethod = Calculator.class.getDeclaredMethod("subtract", int.class, int.class);
            subtractMethod.setAccessible(true); // 允许访问私有方法
            int difference = (int) subtractMethod.invoke(calculator, 5, 3);
            System.out.println("Difference: " + difference); // 输出: Difference: 2

            // 5. 调用公共方法并打印结果
            Method displayMethod = Calculator.class.getMethod("displayResult", int.class);
            displayMethod.invoke(calculator, sum); // 输出: Result: 8

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


//结果
Public Methods:
add
displayResult

All Declared Methods:
add
subtract
displayResult

Sum: 8
Difference: 2
Result: 8

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值