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圣经