【JavaSE】枚举

目录

一、定义

二、使用

2.1 switch

2.2 枚举类的常用方法

三、是否可以通过反射调用枚举的构造方法创建实例 不可以

四、枚举的优缺点

五、用枚举实现单例模式


一、定义

Java的枚举是一个特殊的类,一般表示一组常量。类似于26个字母、月份这种有几种固定的取值时,可以将其定义为枚举类型。

定义形式:

修饰符 enum 枚举类:基础类型{

        枚举成员1,枚举成员2

}

public enum MyEnum {
    Math,English,Chinese
}

注意事项

  • 任意两个枚举成员不能具有相同的名称,且它的常数值必须在该枚举的基础类型的范围之内
  • 多个枚举成员之间使用逗号分隔。
  • 当有除了枚举成员之外的属性时,枚举成员必须在第一行并用分号结尾
  • 枚举的基础类型可以不显示的声明,即枚举名后可以不加基础类型
  • 如果没有显式地声明枚举的基础类型,那么意味着它所对应的基础类型是 int

补充:

  • 在Java 中使用 enum 关键字来定义枚举类,其地位与 class、interface 相同
  • 枚举类是一种特殊的类,它和普通的类一样,有自己的成员变量、成员方法、构造方法
  • 枚举类的构造方法默认被 private 修饰(也只能被 private 修饰),所以无法从外部调用构造器(即 Enum 不能实例化),构造器只在构造枚举值时被调用
  • 使用 enum 定义的枚举类默认继承了 java.lang.Enum 类(虽然没有显示继承),并实现了 java.lang.Seriablizable 和 java.lang.Comparable 两个接口
  • 所有的枚举值都是 public static final 的,且非抽象的枚举类不能再派生子类
  • 枚举类的所有实例(枚举值)必须在枚举类的第一行显式地列出,否则这个枚举类将永远不能产生实例。列出这些实例(枚举值)时,系统会自动添加 public static final 修饰,无需程序员显式添加
  • 当定义一个枚举类型时,每一个枚举类型成员都可以看作是 Enum 类的实例,即枚举值是一个对象
  • 与普通类一样,枚举类也可以实现一个或多个接口。枚举类实现接口时,同样要实现该接口的所有方法

二、使用

2.1 switch

public enum MyEnum {
    Math,English,Chinese;

    public static void main(String[] args) {
        MyEnum myEnum = MyEnum.Math;
        switch (myEnum){
            case Math:
                System.out.println("math");
                break;
            case Chinese:
                System.out.println("Chinese");
                break;
            case English:
                System.out.println("english");
                break;
        }
    }
}

2.2 枚举类的常用方法

方法用途
values()以数组形式返回枚举类型的所有成员
ordinal()获取枚举成员的索引位置
valueOf()将普通字符串转换为枚举实例
compareTo()比较两个枚举成员在定义时的顺序
public enum MyEnum {
    Math,English,Chinese;

    public static void main(String[] args) {
        MyEnum[] myEnums = MyEnum.values();
        for (int i = 0; i < myEnums.length; i++) {
            System.out.println(myEnums[i] +"下标是:"+ myEnums[i].ordinal());
        }
    }
}

public enum MyEnum {
    Math,English,Chinese;

    public static void main(String[] args) {
        System.out.println(Math.compareTo(English)); // -1
        System.out.println(Math.compareTo(Chinese)); // -2
    }
}
public enum MyEnum {
    Math,English,Chinese;

    public static void main(String[] args) {
        System.out.println(MyEnum.valueOf("Math"));
        System.out.println(MyEnum.valueOf("Math1"));
    }
}

三、是否可以通过反射调用枚举的构造方法创建实例 不可以

public enum MyEnum {
    Math("Math",1),English("English",2),Chinese("Chinese",3);
    private String name;
    private int key;

    /**
     * 当枚举对象有参数后,需要提供相应的构造函数
     * 枚举的构造函数默认是私有的
     * @param name
     * @param key
     */
    private MyEnum(String name,int key){
        this.name = name;
        this.key = key;
    }

    public static void main(String[] args) {
        try {
            Class<?> c1 = Class.forName("demo2.MyEnum");
            Constructor<?> constructor =  c1.getDeclaredConstructor(String.class,int.class);
            constructor.setAccessible(true);
            MyEnum myEnum = (MyEnum)constructor.newInstance("Java",12);
            System.out.println(myEnum);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

报异常:没有对应的构造方法

原因:自定义的枚举类,都是默认继承java.lang.Enum。因此,需要帮助父类进行构造。

解决方案1:适用super 不可行

解决方案2:枚举的构造函数虽然我们只写了两个,但是默认还添加了两个,因此一共有四个。默认添加的参数通过源码可以看到:

            Constructor<?> constructor =  c1.getDeclaredConstructor(String.class,int.class,String.class,int.class);
            constructor.setAccessible(true);
            MyEnum myEnum = (MyEnum)constructor.newInstance("Java",12,"父类的参数",1);
            System.out.println(myEnum);

 

原因:

四、枚举的优缺点

  • 优点:枚举常量更简单、更安全、枚举具有内置方法
  • 缺点:枚举不可以继承、枚举无法扩展

五、用枚举实现单例模式

public enum TestEnum {
    INSTANCE;
    public TestEnum getInstance(){
        return INSTANCE;
    }

    public static void main(String[] args) {
        TestEnum testEnum1 = INSTANCE.getInstance();
        TestEnum testEnum2 = INSTANCE.getInstance();
        System.out.println(testEnum1 == testEnum2); // true
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘减减

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值