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