← 返回首页

Java反射机制详解

📂 java ⏱ 4 min 660 words

Java反射机制详解

什么是反射

反射是Java在运行时动态获取类信息、创建对象、调用方法和访问字段的能力。它是框架设计的基石。

获取Class对象

public class ReflectionDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        // 方式1:Class.forName()
        Class<?> clazz1 = Class.forName("java.lang.String");

        // 方式2:.class语法
        Class<String> clazz2 = String.class;

        // 方式3:getClass()
        String str = "hello";
        Class<?> clazz3 = str.getClass();

        // 三种方式获取的是同一个Class对象
        System.out.println(clazz1 == clazz2); // true
        System.out.println(clazz2 == clazz3); // true
    }
}

反射创建对象

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

    public User() {
        this.name = "default";
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age + "}";
    }
}

public class CreateObjectDemo {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("com.example.User");

        // 使用无参构造器
        User user1 = (User) clazz.getDeclaredConstructor().newInstance();
        System.out.println(user1);

        // 使用有参构造器
        Constructor<?> constructor = clazz.getDeclaredConstructor(String.class, int.class);
        User user2 = (User) constructor.newInstance("张三", 25);
        System.out.println(user2);
    }
}

反射访问字段

public class FieldDemo {
    public static void main(String[] args) throws Exception {
        User user = new User("张三", 25);
        Class<?> clazz = user.getClass();

        // 获取所有字段(包括private)
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getName() + ": " + field.getType());
        }

        // 获取指定字段
        Field nameField = clazz.getDeclaredField("name");

        // 设置可访问(访问private字段)
        nameField.setAccessible(true);

        // 读取字段值
        String name = (String) nameField.get(user);
        System.out.println("name = " + name);

        // 设置字段值
        nameField.set(user, "李四");
        System.out.println("修改后: " + user);

        // 修改static字段
        Field staticField = clazz.getDeclaredField("COUNT");
        staticField.setAccessible(true);
        staticField.set(null, 100);
    }
}

反射调用方法

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

    private int multiply(int a, int b) {
        return a * b;
    }

    public static String format(String pattern, Object... args) {
        return String.format(pattern, args);
    }
}

public class MethodDemo {
    public static void main(String[] args) throws Exception {
        Calculator calc = new Calculator();
        Class<?> clazz = calc.getClass();

        // 获取所有方法
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }

        // 调用public方法
        Method addMethod = clazz.getDeclaredMethod("add", int.class, int.class);
        int result = (int) addMethod.invoke(calc, 10, 20);
        System.out.println("10 + 20 = " + result);

        // 调用private方法
        Method multiplyMethod = clazz.getDeclaredMethod("multiply", int.class, int.class);
        multiplyMethod.setAccessible(true);
        int product = (int) multiplyMethod.invoke(calc, 10, 20);
        System.out.println("10 × 20 = " + product);

        // 调用static方法
        Method formatMethod = clazz.getDeclaredMethod("format", String.class, Object[].class);
        String formatted = (String) formatMethod.invoke(null, "Hello %s", new Object[]{"World"});
        System.out.println(formatted);
    }
}

反射获取注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableName {
    String value();
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    String value() default "";
    boolean nullable() default true;
}

@TableName("users")
public class User {
    @Column(value = "user_name", nullable = false)
    private String name;

    @Column("user_age")
    private int age;
}

public class AnnotationDemo {
    public static void main(String[] args) {
        Class<?> clazz = User.class;

        // 获取类注解
        TableName tableName = clazz.getAnnotation(TableName.class);
        System.out.println("表名: " + tableName.value());

        // 获取字段注解
        for (Field field : clazz.getDeclaredFields()) {
            Column column = field.getAnnotation(Column.class);
            if (column != null) {
                System.out.println(field.getName() + " -> " +
                    column.value() + ", nullable=" + column.nullable());
            }
        }
    }
}

反射实现简易ORM框架

public class SimpleORM {
    public static <T> T findById(Connection conn, Class<T> clazz, Object id) throws Exception {
        TableName table = clazz.getAnnotation(TableName.class);
        if (table == null) throw new RuntimeException("缺少@TableName注解");

        String sql = "SELECT * FROM " + table.value() + " WHERE id = ?";
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setObject(1, id);
        ResultSet rs = ps.executeQuery();

        if (rs.next()) {
            T obj = clazz.getDeclaredConstructor().newInstance();
            for (Field field : clazz.getDeclaredFields()) {
                Column column = field.getAnnotation(Column.class);
                String columnName = column != null ? column.value() : field.getName();
                field.setAccessible(true);
                field.set(obj, rs.getObject(columnName));
            }
            return obj;
        }
        return null;
    }
}

性能优化

public class ReflectionPerformance {
    // 缓存Method/Field/Constructor
    private static final Map<String, Method> methodCache = new ConcurrentHashMap<>();

    public static Method getMethod(Class<?> clazz, String name, Class<?>... paramTypes)
            throws NoSuchMethodException {
        String key = clazz.getName() + "." + name;
        return methodCache.computeIfAbsent(key, k -> {
            try {
                return clazz.getDeclaredMethod(name, paramTypes);
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
        });
    }

    // 使用MethodHandle替代反射(Java 7+)
    private static final MethodHandles.Lookup lookup = MethodHandles.lookup();

    public static void methodHandleDemo() throws Throwable {
        MethodType type = MethodType.methodType(String.class, int.class);
        MethodHandle handle = lookup.findVirtual(String.class, "substring", type);
        String result = (String) handle.invoke("Hello World", 6);
        System.out.println(result); // World
    }
}

总结

反射是Java动态性的核心,但使用时要注意性能开销。建议在框架中使用反射,业务代码中谨慎使用。