数据结构:枚举

概念


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

比如下面的例子:

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

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

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

public enum TestEnum {
    RED,BLACK,GREEN;
}

创建枚举类


使用

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

public enum TestEnum {
    RED,GREEN,BLACK;

    public static void main(String[] args) {
        TestEnum color = RED;//定义目标颜色
        switch(color){
            case GREEN:
                System.out.println("GREEN");
                break;
            case RED:
                System.out.println("RED");
                break;
            case BLACK:
                System.out.println("BLACK");
                break;
            default:
                System.out.println("error");
                break;
        }
    }
}

2.常用方法

方法名称

描述

values()

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

ordinal()

获取枚举成员索引位置

valueOf()

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

compareTo()

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

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

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

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

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


枚举的构造方法

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

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

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


枚举和反射

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

我们来试试看

    public static void func() throws ClassNotFoundException, NoSuchMethodException,
            InvocationTargetException, InstantiationException,
            IllegalAccessException {
        //反射Enum类
        Class<?> c1 = Class.forName("demo2.TestEnum");
        //获取Enum类里面私有变量的类型
        Constructor<?> constructor = c1.getDeclaredConstructor(int.class, String.class);
        constructor.setAccessible(true);//私有的要设置true,允许获取
        //实例化新对象
        TestEnum testEnum = (TestEnum) constructor.newInstance(6,"棕色");
        System.out.println(testEnum);
    }

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException,
            InvocationTargetException, InstantiationException,
            IllegalAccessException {
        func();
    }

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

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

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

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

(Enum里面的构造函数)

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

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

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

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

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

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值