文章目录

  • 简介
  • 作用
  • JDK API
  • 根据枚举名称返回枚举中的数据


简介

Java反射(Reflection)是指在运行时能够获取类的信息、创建对象、调用方法、访问属性等。它允许程序在运行时动态地操作一个类,而不需要提前知道这个类的名称或者结构。反射机制主要用于框架开发和底层库的实现。

java enum 获取枚举集合 java获取枚举名称_开发语言

作用

Java反射的主要作用有以下几点:

  1. 在运行时获取类的信息,如类名、构造方法、成员变量、成员方法等。
  2. 创建对象实例,可以通过Class类的newInstance()方法或者Constructor类的newInstance()方法来创建对象。
  3. 调用方法,可以通过Method类的invoke()方法来调用指定对象的方法。
  4. 访问属性,可以通过Field类的get()方法和set()方法来访问和修改对象的私有属性。
  5. 实现动态代理,通过反射机制可以方便地实现动态代理设计模式。
  6. 实现框架和底层库的功能,如Spring框架、Hibernate框架等都大量使用了反射机制。

JDK API

在JDK中,反射相关的API可以分为以下几个方面:

  1. 获取反射的Class对象:这是反射中的基础步骤,要获取一个类或调用一个类的方法,我们首先需要获取到该类的 Class 对象。
Class<?> clazz = Class.forName("java.util.ArrayList");
   System.out.println(clazz);
  1. 通过反射创建类对象:可以使用Constructor类的newInstance()方法或者Class类的newInstance()方法来创建对象实例。
Object obj = clazz.newInstance();
  1. 通过反射获取类属性方法及构造器:可以使用Class类的getDeclaredFields()、getDeclaredMethods()和getDeclaredConstructors()等方法来获取类的属性、方法和构造器。
public static void main(String[] args)
            throws Exception {
        Class<?> clazz = Class.forName("java.util.ArrayList");
        System.out.println(Arrays.toString(clazz.getDeclaredFields()));
        System.out.println(Arrays.toString(clazz.getDeclaredMethods()));
        System.out.println(Arrays.toString(clazz.getDeclaredConstructors()));
    }
  1. 访问属性:可以通过Field类的get()方法和set()方法来访问和修改对象的私有属性。
    示例:创建了一个Person对象,并使用反射修改了其name字段的值:
public class ReflectionDemo {
    public static void main(String[] args) {
        try {
            // 创建一个Person对象
            Person person = new Person("张三", 25);
            // 获取Person类的Class对象
            Class<?> clazz = person.getClass();
            // 获取name字段
            Field nameField = clazz.getDeclaredField("name");
            // 设置name字段可访问
            nameField.setAccessible(true);
            // 设置name字段值为"李四"
            nameField.set(person, "李四");
            // 输出修改后的Person对象
            System.out.println(person);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

class Person {
    private String name;
    private int age;

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
  1. 调用方法:可以通过Method类的invoke()方法来调用指定对象的方法。
Class<?> clazz = Class.forName("java.util.ArrayList");
  Object obj = clazz.newInstance();
  Method method = clazz.getDeclaredMethod("add", Object.class);
  method.invoke(obj, "Hello");
  System.out.println(obj);

根据枚举名称返回枚举中的数据

系统中普遍存在枚举类,枚举类主要用于表示固定数量的可能值,枚举类在需要表示一组固定值的场景中非常有用,比如订单的状态分为已下单和未下单,erp分为出库和入库。我们根据上面的知识最后实现一个扫描指定路径的,根据枚举名称返回枚举中数据的示例:

@Slf4j
public class EnumUtil {

    public static Map<String, List<DictionaryVo>> enums = null;

    static {
        try {
            enums = getEnums();
        } catch (InvocationTargetException | IllegalAccessException e) {
            log.error("error enum to vo", e);
        }
    }

    // 扫描的包路径
    private static final String basePackage = "com.jianguozh.anpin.common.constant";

    private static Map<String, List<DictionaryVo>> getEnums() throws InvocationTargetException, IllegalAccessException {
        //扫描该包路径下所有class文件
        Set<Class<?>> classes = ClassUtil.scanPackage(basePackage);
        Map<String, List<DictionaryVo>> enums = new HashMap<>();
        List<DictionaryVo> list;
        for (Class<?> aClass : classes) {
            if (ClassUtil.isEnum(aClass)) {
                Method keyMethod = ClassUtil.getDeclaredMethod(aClass, "getCode");
                Method valueMethod = ClassUtil.getDeclaredMethod(aClass, "getDisplayName");
                if (keyMethod == null || valueMethod == null) {
                    continue;
                }
                Object[] objs = aClass.getEnumConstants();
                // 装载当前枚举所有值
                list = new ArrayList<>();
                for (Object obj : objs) {
                    String code = keyMethod.invoke(obj).toString();
                    String val = valueMethod.invoke(obj).toString();
                    list.add(new DictionaryVo(code, val));
                }
                // 装载当前枚举list
                String enumName = aClass.getName()
                        .substring(aClass.getName().lastIndexOf(".") + 1);
                enums.put(enumName, list);
            }
        }
        return enums;
    }
}