18.1.6 反射机制原理与性能考量

1. 反射机制基础

1.1 反射的定义

反射是Java提供的一种机制,允许程序在运行时检查和操作类、接口、字段和方法的信息,即使在编译时不知道它们的名称。

1.2 反射的核心类

// 核心反射类
Class<?> clazz = String.class;
Field[] fields = clazz.getDeclaredFields();
Method[] methods = clazz.getDeclaredMethods();
Constructor<?>[] constructors = clazz.getDeclaredConstructors();

// 反射相关的主要类
// java.lang.Class - 类的元数据
// java.lang.reflect.Field - 字段信息
// java.lang.reflect.Method - 方法信息
// java.lang.reflect.Constructor - 构造器信息
// java.lang.reflect.Modifier - 修饰符工具类

2. 获取Class对象的方式

2.1 三种获取Class对象的方法

public class GetClassDemo {
    public void demonstrateGetClass() throws ClassNotFoundException {
        // 方式1: 通过类名.class
        Class<String> clazz1 = String.class;
        System.out.println("方式1: " + clazz1.getName());
        
        // 方式2: 通过对象.getClass()
        String str = "Hello";
        Class<?> clazz2 = str.getClass();
        System.out.println("方式2: " + clazz2.getName());
        
        // 方式3: 通过Class.forName()
        Class<?> clazz3 = Class.forName("java.lang.String");
        System.out.println("方式3: " + clazz3.getName());
        
        // 验证三种方式获取的是同一个Class对象
        System.out.println("clazz1 == clazz2: " + (clazz1 == clazz2));
        System.out.println("clazz2 == clazz3: " + (clazz2 == clazz3));
    }
    
    // 基本类型的Class对象
    public void primitiveClassDemo() {
        Class<Integer> integerClass = Integer.class;
        Class<Integer> intClass = int.class;
        Class<Integer> integerType = Integer.TYPE;
        
        System.out.println("Integer.class: " + integerClass);
        System.out.println("int.class: " + intClass);
        System.out.println("Integer.TYPE: " + integerType);
        System.out.println("int.class == Integer.TYPE: " + (intClass == integerType));
    }
}

3. 反射操作详解

3.1 类信息获取

public class ClassInfoDemo {
    public void analyzeClass(Class<?> clazz) {
        System.out.println("=== 类信息分析 ===");
        
        // 基本信息
        System.out.println("类名: " + clazz.getName());
        System.out.println("简单类名: " + clazz.getSimpleName());
        System.out.println("包名: " + clazz.getPackage().getName());
        System.out.println("修饰符: " + Modifier.toString(clazz.getModifiers()));
        
        // 继承关系
        Class<?> superClass = clazz.getSuperclass();
        if (superClass != null) {
            System.out.println("父类: " + superClass.getName());
        }
        
        // 实现的接口
        Class<?>[] interfaces = clazz.getInterfaces();
        System.out.println("实现的接口数量: " + interfaces.length);
        for (Class<?> intf : interfaces) {
            System.out.println("  - " + intf.getName());
        }
        
        // 类型判断
        System.out.println("是否为接口: " + clazz.isInterface());
        System.out.println("是否为抽象类: " + Modifier.isAbstract(clazz.getModifiers()));
        System.out.println("是否为枚举: " + clazz.isEnum());
        System.out.println("是否为注解: " + clazz.isAnnotation());
    }
    
    public static void main(String[] args) {
        new ClassInfoDemo().analyzeClass(ArrayList.class);
    }
}

3.2 字段操作

public class FieldReflectionDemo {
    private String privateField = "私有字段";
    public String publicField = "公有字段";
    protected String protectedField = "受保护字段";
    static String staticField = "静态字段";
    
    public void demonstrateFieldReflection() throws Exception {
        Class<?> clazz = this.getClass();
        
        // 获取所有字段
        System.out.println("=== 所有声明的字段 ===");
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.printf("字段: %s, 类型: %s, 修饰符: %s%n",
                field.getName(),
                field.getType().getSimpleName(),
                Modifier.toString(field.getModifiers()));
        }
        
        // 获取公有字段
        System.out.println("\n=== 公有字段 ===");
        Field[] publicFields = clazz.getFields();
        for (Field field : publicFields) {
            System.out.println("公有字段: " + field.getName());
        }
        
        // 访问私有字段
        Field privateField = clazz.getDeclaredField("privateField");
        privateField.setAccessible(true);  // 设置可访问
        String value = (String) privateField.get(this);
        System.out.println("私有字段值: " + value);
        
        // 修改私有字段
        privateField.set(this, "修改后的私有字段");
        System.out.println("修改后的私有字段值: " + privateField.get(this));
        
        // 访问静态字段
        Field staticField = clazz.getDeclaredField("staticField");
        String staticValue = (String) staticField.get(null);  // 静态字段传null
        System.out.println("静态字段值: " + staticValue);
    }
    
    public static void main(String[] args) throws Exception {
        new FieldReflectionDemo().demonstrateFieldReflection();
    }
}

3.3 方法操作

public class MethodReflectionDemo {
    
    public void publicMethod(String param) {
        System.out.println("公有方法被调用: " + param);
    }
    
    private String privateMethod(String param1, int param2) {
        return "私有方法返回: " + param1 + ", " + param2;
    }
    
    public static void staticMethod() {
        System.out.println("静态方法被调用");
    }
    
    public void overloadedMethod() {
        System.out.println("无参重载方法");
    }
    
    public void overloadedMethod(String param) {
        System.out.println("有参重载方法: " + param);
    }
    
    public void demonstrateMethodReflection() throws Exception {
        Class<?> clazz = this.getClass();
        
        // 获取所有声明的方法
        System.out.println("=== 所有声明的方法 ===");
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method method : declaredMethods) {
            System.out.printf("方法: %s, 返回类型: %s, 参数个数: %d%n",
                method.getName(),
                method.getReturnType().getSimpleName(),
                method.getParameterCount());
            
            // 打印参数类型
            Class<?>[] paramTypes = method.getParameterTypes();
            for (int i = 0; i < paramTypes.length; i++) {
                System.out.println("  参数" + i + ": " + paramTypes[i].getSimpleName());
            }
        }
        
        // 调用公有方法
        Method publicMethod = clazz.getMethod("publicMethod", String.class);
        publicMethod.invoke(this, "测试参数");
        
        // 调用私有方法
        Method privateMethod = clazz.getDeclaredMethod("privateMethod", String.class, int.class);
        privateMethod.setAccessible(true);
        String result = (String) privateMethod.invoke(this, "测试", 123);
        System.out.println("私有方法返回值: " + result);
        
        // 调用静态方法
        Method staticMethod = clazz.getMethod("staticMethod");
        staticMethod.invoke(null);  // 静态方法传null
        
        // 调用重载方法
        Method overloaded1 = clazz.getMethod("overloadedMethod");
        Method overloaded2 = clazz.getMethod("overloadedMethod", String.class);
        overloaded1.invoke(this);
        overloaded2.invoke(this, "重载参数");
    }
    
    public static void main(String[] args) throws Exception {
        new MethodReflectionDemo().demonstrateMethodReflection();
    }
}

3.4 构造器操作

public class ConstructorReflectionDemo {
    private String name;
    private int age;
    
    public ConstructorReflectionDemo() {
        this.name = "默认名称";
        this.age = 0;
    }
    
    public ConstructorReflectionDemo(String name) {
        this.name = name;
        this.age = 0;
    }
    
    private ConstructorReflectionDemo(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public void demonstrateConstructorReflection() throws Exception {
        Class<?> clazz = ConstructorReflectionDemo.class;
        
        // 获取所有构造器
        System.out.println("=== 所有声明的构造器 ===");
        Constructor<?>[] constructors = clazz.getDeclaredConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.printf("构造器参数个数: %d, 修饰符: %s%n",
                constructor.getParameterCount(),
                Modifier.toString(constructor.getModifiers()));
            
            Class<?>[] paramTypes = constructor.getParameterTypes();
            for (int i = 0; i < paramTypes.length; i++) {
                System.out.println("  参数" + i + ": " + paramTypes[i].getSimpleName());
            }
   

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

Java面试圣经 文章被收录于专栏

Java面试圣经,带你练透java圣经

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务