Java案例如何反射获取类信息?

wen java案例 12

本文目录导读:

Java案例如何反射获取类信息?

  1. 获取Class对象
  2. 获取类基本信息
  3. 获取类的成员信息
  4. 获取注解信息
  5. 完整示例代码
  6. 注意事项

我来详细讲解Java中如何通过反射获取类信息,包括各种核心API的使用方法。

获取Class对象

public class ReflectionDemo {
    public static void main(String[] args) throws Exception {
        // 方式1:通过Class.forName()
        Class<?> clazz1 = Class.forName("com.example.User");
        // 方式2:通过对象.getClass()
        User user = new User();
        Class<?> clazz2 = user.getClass();
        // 方式3:通过类.class
        Class<?> clazz3 = User.class;
        // 方式4:通过类加载器
        Class<?> clazz4 = ClassLoader.getSystemClassLoader().loadClass("com.example.User");
    }
}

获取类基本信息

public class ClassInfoDemo {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = User.class;
        // 获取类名
        System.out.println("完整类名:" + clazz.getName());           // com.example.User
        System.out.println("简单类名:" + clazz.getSimpleName());     // User
        System.out.println("包名:" + clazz.getPackage().getName()); // com.example
        // 获取访问修饰符
        int modifiers = clazz.getModifiers();
        System.out.println("修饰符:" + Modifier.toString(modifiers));
        // 获取父类
        Class<?> superClass = clazz.getSuperclass();
        System.out.println("父类:" + superClass.getName());
        // 获取实现的接口
        Class<?>[] interfaces = clazz.getInterfaces();
        for (Class<?> inter : interfaces) {
            System.out.println("实现的接口:" + inter.getName());
        }
    }
}

获取类的成员信息

1 获取字段(Field)

public class FieldInfoDemo {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = User.class;
        // 获取所有公共字段(包括继承的)
        Field[] publicFields = clazz.getFields();
        // 获取所有字段(不包括继承的)
        Field[] allFields = clazz.getDeclaredFields();
        for (Field field : allFields) {
            System.out.println("字段名:" + field.getName());
            System.out.println("字段类型:" + field.getType().getName());
            System.out.println("修饰符:" + Modifier.toString(field.getModifiers()));
            // 处理私有字段
            field.setAccessible(true);
            User user = new User();
            if (field.getName().equals("name")) {
                field.set(user, "张三");
                System.out.println("设置值后:" + field.get(user));
            }
        }
    }
}

2 获取方法(Method)

public class MethodInfoDemo {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = User.class;
        // 获取所有公共方法(包括继承的)
        Method[] publicMethods = clazz.getMethods();
        // 获取所有方法(不包括继承的)
        Method[] allMethods = clazz.getDeclaredMethods();
        for (Method method : allMethods) {
            System.out.println("方法名:" + method.getName());
            System.out.println("返回类型:" + method.getReturnType().getName());
            System.out.println("修饰符:" + Modifier.toString(method.getModifiers()));
            // 获取参数类型
            Class<?>[] paramTypes = method.getParameterTypes();
            for (Class<?> paramType : paramTypes) {
                System.out.println("参数类型:" + paramType.getName());
            }
            // 获取异常类型
            Class<?>[] exceptionTypes = method.getExceptionTypes();
            for (Class<?> exType : exceptionTypes) {
                System.out.println("抛出异常:" + exType.getName());
            }
        }
        // 调用方法
        User user = new User();
        Method setNameMethod = clazz.getMethod("setName", String.class);
        setNameMethod.invoke(user, "李四");
        Method getNameMethod = clazz.getMethod("getName");
        String name = (String) getNameMethod.invoke(user);
        System.out.println("调用方法结果:" + name);
    }
}

3 获取构造方法(Constructor)

public class ConstructorInfoDemo {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = User.class;
        // 获取所有公共构造方法
        Constructor<?>[] publicConstructors = clazz.getConstructors();
        // 获取所有构造方法
        Constructor<?>[] allConstructors = clazz.getDeclaredConstructors();
        for (Constructor<?> constructor : allConstructors) {
            System.out.println("构造方法名:" + constructor.getName());
            // 获取参数类型
            Class<?>[] paramTypes = constructor.getParameterTypes();
            for (int i = 0; i < paramTypes.length; i++) {
                System.out.println("参数" + i + "类型:" + paramTypes[i].getName());
            }
        }
        // 通过构造方法创建对象
        // 无参构造
        User user1 = (User) clazz.getConstructor().newInstance();
        // 有参构造
        Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
        User user2 = (User) constructor.newInstance("王五", 25);
    }
}

获取注解信息

public class AnnotationInfoDemo {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = AnnotatedUser.class;
        // 获取类上的注解
        Annotation[] classAnnotations = clazz.getAnnotations();
        if (clazz.isAnnotationPresent(Deprecated.class)) {
            System.out.println("该类被标记为@Deprecated");
        }
        // 获取字段上的注解
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(MyAnnotation.class)) {
                MyAnnotation annotation = field.getAnnotation(MyAnnotation.class);
                System.out.println("字段:" + field.getName() + 
                                 " 注解值:" + annotation.value());
            }
        }
        // 获取方法上的注解
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(Override.class)) {
                System.out.println("方法:" + method.getName() + " 使用了@Override");
            }
        }
    }
}

完整示例代码

// 示例类
class User {
    private String name;
    private int age;
    public User() {}
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    private void privateMethod() {
        System.out.println("私有方法被调用");
    }
    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age + "}";
    }
}
// 反射工具类
public class ReflectionUtils {
    // 打印类的完整信息
    public static void printClassInfo(Class<?> clazz) {
        System.out.println("========== " + clazz.getName() + " 类信息 ==========");
        // 基本类信息
        System.out.println("包名:" + clazz.getPackage().getName());
        System.out.println("修饰符:" + Modifier.toString(clazz.getModifiers()));
        System.out.println("父类:" + clazz.getSuperclass().getName());
        // 接口信息
        System.out.println("\n实现的接口:");
        for (Class<?> inter : clazz.getInterfaces()) {
            System.out.println("  - " + inter.getName());
        }
        // 字段信息
        System.out.println("\n所有字段:");
        for (Field field : clazz.getDeclaredFields()) {
            System.out.println("  " + Modifier.toString(field.getModifiers()) + 
                             " " + field.getType().getSimpleName() + 
                             " " + field.getName());
        }
        // 构造方法信息
        System.out.println("\n所有构造方法:");
        for (Constructor<?> constructor : clazz.getDeclaredConstructors()) {
            System.out.print("  " + Modifier.toString(constructor.getModifiers()) + 
                           " " + constructor.getName() + "(");
            Class<?>[] paramTypes = constructor.getParameterTypes();
            for (int i = 0; i < paramTypes.length; i++) {
                System.out.print(paramTypes[i].getSimpleName());
                if (i < paramTypes.length - 1) {
                    System.out.print(", ");
                }
            }
            System.out.println(")");
        }
        // 方法信息
        System.out.println("\n所有方法:");
        for (Method method : clazz.getDeclaredMethods()) {
            System.out.print("  " + Modifier.toString(method.getModifiers()) + 
                           " " + method.getReturnType().getSimpleName() + 
                           " " + method.getName() + "(");
            Class<?>[] paramTypes = method.getParameterTypes();
            for (int i = 0; i < paramTypes.length; i++) {
                System.out.print(paramTypes[i].getSimpleName());
                if (i < paramTypes.length - 1) {
                    System.out.print(", ");
                }
            }
            System.out.println(")");
        }
    }
    // 动态调用方法
    public static Object invokeMethod(Object obj, String methodName, 
                                      Object... args) throws Exception {
        Class<?> clazz = obj.getClass();
        Class<?>[] paramTypes = new Class[args.length];
        for (int i = 0; i < args.length; i++) {
            paramTypes[i] = args[i].getClass();
        }
        Method method = clazz.getMethod(methodName, paramTypes);
        return method.invoke(obj, args);
    }
}
// 测试类
public class Main {
    public static void main(String[] args) throws Exception {
        // 打印类信息
        ReflectionUtils.printClassInfo(User.class);
        // 动态创建对象
        Class<?> clazz = User.class;
        User user = (User) clazz.getConstructor(String.class, int.class)
                               .newInstance("小明", 20);
        // 动态调用方法
        String result = (String) ReflectionUtils.invokeMethod(user, "getName");
        System.out.println("\n动态调用结果:" + result);
        // 修改私有字段
        Field nameField = clazz.getDeclaredField("name");
        nameField.setAccessible(true);
        nameField.set(user, "小红");
        System.out.println("修改私有字段后:" + user);
    }
}

注意事项

  • 性能开销:反射操作比直接调用慢,避免在循环中频繁使用
  • 安全检查:访问私有成员时需要使用 setAccessible(true)
  • 异常处理:反射操作会抛出多个受检异常,需要适当处理
  • 安全问题:反射可以绕过访问控制,可能破坏封装性
  • 泛型信息:运行时泛型信息会被擦除,需要特殊处理

通过反射,你可以实现灵活的代码,适合框架开发、动态代理、序列化等场景。

抱歉,评论功能暂时关闭!