• 数据结构:枚举


    概念


    枚举主要用途是:将一组常量组织起来,在这之前表示一组常量通常使用定义常量的方式:

    比如下面的例子:

    1. public static final int RED = 1;
    2. public static final int GREEN = 2;
    3. public static final int BLACK = 3;

    利用常量表示RED,GREEN,BLACK既繁琐又容易出错

    如果程序里面还有一个int a = 1,那程序可能会认为是RED,用枚举来组织可以轻松解决这些问题

    1. public enum TestEnum {
    2. RED,BLACK,GREEN;
    3. }

    创建枚举类


    使用

    1.用switch语句来匹配对应的颜色

    1. public enum TestEnum {
    2. RED,GREEN,BLACK;
    3. public static void main(String[] args) {
    4. TestEnum color = RED;//定义目标颜色
    5. switch(color){
    6. case GREEN:
    7. System.out.println("GREEN");
    8. break;
    9. case RED:
    10. System.out.println("RED");
    11. break;
    12. case BLACK:
    13. System.out.println("BLACK");
    14. break;
    15. default:
    16. System.out.println("error");
    17. break;
    18. }
    19. }
    20. }

    2.常用方法

    方法名称

    描述

    values()

    以数组的形式返回枚举成员

    ordinal()

    获取枚举成员索引位置

    valueOf()

    将普通字符串转成枚举实例

    compareTo()

    比较两个枚举成员在定义时的顺序

    这些方法是被继承过来的,默认继承于枚举类

    但是我们在这里面没有找到values,那这个方法怎么可以被调用呢?

    这是由于java编译器在对enum关键字进行处理时,实际上是将enum转换成为了java.lang.Enum类的一个子类来完成,而这个子类中含有values()静态方法。这一点,可以通过反编译enum类来查看。

    如图,通过javap反编译enum枚举类,可以看到编译器在对enum处理时,实际上是转换成了Enum的一个子类来实现的,里面可以看到有values()静态方法的声明。


    枚举的构造方法

    ⚠枚举构造方法默认是private的,所以写不写private没影响

    1. RED(1,"红色"),
    2. GREEN(2,"绿色"),
    3. BLACK(3,"黑色");
    4. private int ordinal;
    5. private String color;
    6. TestEnum(int ordinal, String color){
    7. this.ordinal = ordinal;
    8. this.color = color;
    9. }

    这也是枚举本身的一个缺点,它无法继承也无法扩展


    枚举和反射

    既然枚举里面的构造方法是私有的,那我们可不可以用反射来实例化一个枚举对象呢?

    我们来试试看

    1. public static void func() throws ClassNotFoundException, NoSuchMethodException,
    2. InvocationTargetException, InstantiationException,
    3. IllegalAccessException {
    4. //反射Enum类
    5. Class c1 = Class.forName("demo2.TestEnum");
    6. //获取Enum类里面私有变量的类型
    7. Constructor constructor = c1.getDeclaredConstructor(int.class, String.class);
    8. constructor.setAccessible(true);//私有的要设置true,允许获取
    9. //实例化新对象
    10. TestEnum testEnum = (TestEnum) constructor.newInstance(6,"棕色");
    11. System.out.println(testEnum);
    12. }
    13. public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException,
    14. InvocationTargetException, InstantiationException,
    15. IllegalAccessException {
    16. func();
    17. }

    当我们运行起来的时候,发现程序报错了

    报错信息说我没有int, java.lang.String这两个参数

    诶我在前面的构造方法不是传入这两个参数了吗?

    其实我一开始写的TestEnum是继承于Enum这个类的,相当于我们既要反射TestEnum类,也要反射Enum类

    (Enum里面的构造函数)

    也就是说我们在c1.getDeclaredConstructor()里面传入四个参数,🆗我照做

    但是怎么又抛了一个异常给我

    我们点开Constructor的源码,注意到这句话

    这句话意思是当我们试图创建一个枚举类时,程序就会抛一个异常出来,不允许我们创建这个类

    所以不可以用反射来实例化一个枚举对象

    换句话说,枚举十分安全。特别地,用枚举来实现单例模式非常安全

  • 相关阅读:
    Ansible playbook的block
    应用实战|从头开始开发记账本1:如何获取BaaS服务
    如何在 K8S 集群范围使用 imagePullSecret?
    怎样在小程序中直播
    赴日IT 35岁以上程序员能申请日本技术人文签证吗?
    管理数据质量、准确性和一致性的策略
    面向对象之元类
    v-model绑定导致的element UI文本框输入第一次值后被绑定,导致空文本框无法再输入文字
    支持阅后即焚的即时在线聊天软件工具—J2L3x 消息删除和回复功能值得推荐
    SQL注入漏洞(postgresql注入)
  • 原文地址:https://blog.csdn.net/hellg/article/details/134409890