Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 321|回复: 0

[默认分类] java enum的用法详解

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-7-10 13:27:00 | 显示全部楼层 |阅读模式

    java Enum原理

    1. public enum Size{ SMALL, MEDIUM, LARGE, EXTRA_LARGE };
    复制代码


    实际上,这个声明定义的类型是一个类,它刚好有四个实例,在此尽量不要构造新对象。
    因此,在比较两个枚举类型的值时,永远不需要调用equals方法,而直接使用"=="就可以了。(equals()方法也是直接使用==,  两者是一样的效果)
    Java Enum类型的语法结构尽管和java类的语法不一样,应该说差别比较大。但是经过编译器编译之后产生的是一个class文件。该class文件经过反编译可以看到实际上是生成了一个类,该类继承了java.lang.Enum<E>。
       例如:

    1. public enum WeekDay {
    2.      Mon("Monday"), Tue("Tuesday"), Wed("Wednesday"), Thu("Thursday"), Fri( "Friday"), Sat("Saturday"), Sun("Sunday");
    3.      private final String day;
    4.      private WeekDay(String day) {
    5.             this.day = day;
    6.      }
    7.     public static void printDay(int i){
    8.        switch(i){
    9.            case 1: System.out.println(WeekDay.Mon); break;
    10.            case 2: System.out.println(WeekDay.Tue);break;
    11.            case 3: System.out.println(WeekDay.Wed);break;
    12.             case 4: System.out.println(WeekDay.Thu);break;
    13.            case 5: System.out.println(WeekDay.Fri);break;
    14.            case 6: System.out.println(WeekDay.Sat);break;
    15.             case 7: System.out.println(WeekDay.Sun);break;
    16.            default:System.out.println("wrong number!");
    17.          }
    18.      }
    19.     public String getDay() {
    20.         return day;
    21.      }
    22. }
    复制代码
    WeekDay经过反编译(javap WeekDay命令)之后得到的内容如下(去掉了汇编代码):

    1. public final class WeekDay extends java.lang.Enum{
    2.     public static final WeekDay Mon;
    3.     public static final WeekDay Tue;
    4.     public static final WeekDay Wed;
    5.     public static final WeekDay Thu;
    6.     public static final WeekDay Fri;
    7.     public static final WeekDay Sat;
    8.     public static final WeekDay Sun;
    9.     static {};
    10.     public static void printDay(int);
    11.     public java.lang.String getDay();
    12.     public static WeekDay[] values();
    13.     public static WeekDay valueOf(java.lang.String);
    14. }
    复制代码
    用法一:常量
    在JDK1.5 之前,我们定义常量都是: public static fianl.... 。现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法。
    1. public enum Color {  
    2.   RED, GREEN, BLANK, YELLOW  
    3. }
    复制代码


    用法二:switch
    JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强。
    1. enum Signal {
    2.         GREEN, YELLOW, RED
    3.     }
    4.     public class TrafficLight {
    5.         Signal color = Signal.RED;
    6.         public void change() {
    7.             switch (color) {
    8.             case RED:
    9.                 color = Signal.GREEN;
    10.                 break;
    11.             case YELLOW:
    12.                 color = Signal.RED;
    13.                 break;
    14.             case GREEN:
    15.                 color = Signal.YELLOW;
    16.                 break;
    17.             }
    18.         }
    19.     }
    复制代码


    用法三:向枚举中添加新方法
    如果打算自定义自己的方法,那么必须在enum实例序列的最后添加一个分号。而且 Java 要求必须先定义 enum 实例。
    1. public enum Color {
    2.         RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
    3.         // 成员变量
    4.         private String name;
    5.         private int index;
    6.         // 构造方法
    7.         private Color(String name, int index) {
    8.             this.name = name;
    9.             this.index = index;
    10.         }
    11.         // 普通方法
    12.         public static String getName(int index) {
    13.             for (Color c : Color.values()) {
    14.                 if (c.getIndex() == index) {
    15.                     return c.name;
    16.                 }
    17.             }
    18.             return null;
    19.         }
    20.         // get set 方法
    21.         public String getName() {
    22.             return name;
    23.         }
    24.         public void setName(String name) {
    25.             this.name = name;
    26.         }
    27.         public int getIndex() {
    28.             return index;
    29.         }
    30.         public void setIndex(int index) {
    31.             this.index = index;
    32.         }
    33.     }
    复制代码


    用法四:覆盖枚举的方法
    下面给出一个toString()方法覆盖的例子。
    1. public class Test {
    2.     public enum Color {
    3.         RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
    4.         // 成员变量
    5.         private String name;
    6.         private int index;
    7.         // 构造方法
    8.         private Color(String name, int index) {
    9.             this.name = name;
    10.             this.index = index;
    11.         }
    12.         // 覆盖方法
    13.         @Override
    14.         public String toString() {
    15.             return this.index + "_" + this.name;
    16.         }
    17.     }
    18.     public static void main(String[] args) {
    19.         System.out.println(Color.RED.toString());
    20.     }
    21. }
    复制代码


    用法五:实现接口
    所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类。
    1. public interface Behaviour {
    2.         void print();
    3.         String getInfo();
    4.     }
    5.     public enum Color implements Behaviour {
    6.         RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
    7.         // 成员变量
    8.         private String name;
    9.         private int index;
    10.         // 构造方法
    11.         private Color(String name, int index) {
    12.             this.name = name;
    13.             this.index = index;
    14.         }
    15.         // 接口方法
    16.         @Override
    17.         public String getInfo() {
    18.             return this.name;
    19.         }
    20.         // 接口方法
    21.         @Override
    22.         public void print() {
    23.             System.out.println(this.index + ":" + this.name);
    24.         }
    25.     }
    复制代码


    用法六:使用接口组织枚举



    1. public interface Food {        enum Coffee implements Food {            BLACK_COFFEE, DECAF_COFFEE, LATTE, CAPPUCCINO        }        enum Dessert implements Food {            FRUIT, CAKE, GELATO        }    }
    复制代码


    用法七:关于枚举集合的使用
    java.util.EnumSet和java.util.EnumMap是两个枚举集合。EnumSet保证集合中的元素不重复;EnumMap中的 key是enum类型,而value则可以是任意类型。关于这个两个集合的使用就不在这里赘述,可以参考JDK文档
    三、 完整示例代码
    枚举类型的完整演示代码如下:
    1. public class LightTest {
    2.     // 1.定义枚举类型
    3.     public enum Light {
    4.         // 利用构造函数传参
    5.         RED(1), GREEN(3), YELLOW(2);
    6.         // 定义私有变量
    7.         private int nCode;
    8.         // 构造函数,枚举类型只能为私有
    9.         private Light(int _nCode) {
    10.             this.nCode = _nCode;
    11.         }
    12.         @Override
    13.         public String toString() {
    14.             return String.valueOf(this.nCode);
    15.         }
    16.     }
    17.     /**
    18.      *
    19.      * @param args
    20.      */
    21.     public static void main(String[] args) {
    22.         // 1.遍历枚举类型
    23.         System.out.println("演示枚举类型的遍历 ......");
    24.         testTraversalEnum();
    25.         // 2.演示EnumMap对象的使用
    26.         System.out.println("演示EnmuMap对象的使用和遍历.....");
    27.         testEnumMap();
    28.         // 3.演示EnmuSet的使用
    29.         System.out.println("演示EnmuSet对象的使用和遍历.....");
    30.         testEnumSet();
    31.     }
    32.     /**
    33.      *
    34.      * 演示枚举类型的遍历
    35.      */
    36.     private static void testTraversalEnum() {
    37.         Light[] allLight = Light.values();
    38.         for (Light aLight : allLight) {
    39.             System.out.println("当前灯name:" + aLight.name());
    40.             System.out.println("当前灯ordinal:" + aLight.ordinal());
    41.             System.out.println("当前灯:" + aLight);
    42.         }
    43.     }
    44.     /**
    45.      *
    46.      * 演示EnumMap的使用,EnumMap跟HashMap的使用差不多,只不过key要是枚举类型
    47.      */
    48.     private static void testEnumMap() {
    49.         // 1.演示定义EnumMap对象,EnumMap对象的构造函数需要参数传入,默认是key的类的类型
    50.         EnumMap<Light, String> currEnumMap = new EnumMap<Light, String>(
    51.         Light.class);
    52.         currEnumMap.put(Light.RED, "红灯");
    53.         currEnumMap.put(Light.GREEN, "绿灯");
    54.         currEnumMap.put(Light.YELLOW, "黄灯");
    55.         // 2.遍历对象
    56.         for (Light aLight : Light.values()) {
    57.             System.out.println("[key=" + aLight.name() + ",value="
    58.             + currEnumMap.get(aLight) + "]");
    59.         }
    60.     }
    61.     /**
    62.      *
    63.      * 演示EnumSet如何使用,EnumSet是一个抽象类,获取一个类型的枚举类型内容<BR/>
    64.      *
    65.      * 可以使用allOf方法
    66.      */
    67.     private static void testEnumSet() {
    68.         EnumSet<Light> currEnumSet = EnumSet.allOf(Light.class);
    69.         for (Light aLightSetElement : currEnumSet) {
    70.             System.out.println("当前EnumSet中数据为:" + aLightSetElement);
    71.         }
    72.     }
    73. }
    复制代码


    执行结果如下:
    演示枚举类型的遍历 ......
    当前灯name:RED
    当前灯ordinal:0
    当前灯:1
    当前灯name:GREEN
    当前灯ordinal:1
    当前灯:3
    当前灯name:YELLOW
    当前灯ordinal:2
    当前灯:2
    演示EnmuMap对象的使用和遍历.....
    [key=RED,value=红灯]
    [key=GREEN,value=绿灯]
    [key=YELLOW,value=黄灯]
    演示EnmuSet对象的使用和遍历.....
    当前EnumSet中数据为:1
    当前EnumSet中数据为:3
    当前EnumSet中数据为:2



    1. 所有的枚举类型都是Enum类的子类。 它们继承了这个类的许多方法。其中最有用的一个方法是toString(),这个方法能够返回枚举常量名。   toString()方法的逆方法是静态方法valueOf(Class, String). 例如 Light lt = (Light) Enum.valueOf(Light.class, "RED"); 将lt设置为 Light.RED。 每个枚举类型都有一个静态的values()方法,它将返回一个包含全部枚举值的数组。   ordinal()方法返回enum声明中枚举常量的位置,位置从0开始计数。例如  Light.GREEN.ordinal()返回1。   Enum类实现了Comparable接口,  int  compareTo( E other)  如果枚举常量在other之前,则返回一个负值; 如果this==other,则返回0;否则,返回正值。 枚举常量的出现次序在enum 声明中给出。(所以不能直接用<,>符号比较两个枚举值)
    2. 可以创建一个enum类,把它看做一个普通的类。除了它不能继承其他类了。(java是单继承,它已经继承了Enum),
    可以添加其他方法,覆盖它本身的方法
    3. switch()参数可以使用enum了
    4. values()方法是编译器插入到enum定义中的static方法,所以,当你将enum实例向上转型为父类Enum是,values()就不可访问了。解决办法:在Class中有一个getEnumConstants()方法,所以即便Enum接口中没有values()方法,我们仍然可以通过Class对象取得所有的enum实例
    5. 无法从enum继承子类,如果需要扩展enum中的元素,在一个接口的内部,创建实现该接口的枚举,以此将元素进行分组。达到将枚举元素进行分组。
    6. 使用EnumSet代替标志。enum要求其成员都是唯一的,但是enum中不能删除添加元素。
    7. EnumMap的key是enum,value是任何其他Object对象。
    8. enum允许程序员为eunm实例编写方法。所以可以为每个enum实例赋予各自不同的行为。
    9. 使用enum的职责链(Chain of Responsibility) .这个关系到设计模式的职责链模式。以多种不同的方法来解决一个问题。然后将他们链接在一起。当一个请求到来时,遍历这个链,直到链中的某个解决方案能够处理该请求。
    10. 使用enum的状态机
    11. 使用enum多路分发




    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-3-29 00:14 , Processed in 0.373747 second(s), 46 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表