zoukankan      html  css  js  c++  java
  • Java核心类——枚举类

    在Java中,我们可以通过static final来定义常量。例如定义周一到周日:

    public class weekday {
        public static final int SUN = 0;
        public static final int MON = 1;
        public static final int TUE = 2;
        public static final int WED =3;
        public static final int THU = 4;
        public static final int FRI = 5;
        public static final int SAT = 6;
    }

    使用常量的时候,可以这么引用:

    if (day == Weekday.SAT || day == Weekday.SUN) {}

    当然也可以将常量定义为字符串类型。

    无论是int常量还是String常量,使用这些常量来表示一组枚举的时候,
    有一个严重的问题就是,编译器无法检查每个值得合理性。比如:

    if (weekday == 6 || weekday == 7) {
        if (tasks == weekday.MON) {
            // TODO    
        }
    }

    上面代码存在两个问题:
    (1)weekday定义得常量范围是0-6,并不包含7,编译器无法检测不在枚举中得int值
    (2)定义的常量仍可以于其他变量比较,但其用途并非是枚举星期值

    为了让编译器能自动检查某个值在枚举的集合内,并且不同用途的枚举需要不同的类型来标记:

    enum Weekday {
        SUN,MON,TUE,WED,THU,FRI,SAT;
    }
    
    public class catchExample2 {
        public static void main(String[] args) throws Exception {
            Weekday day = Weekday.SUN;
            if (day == Weekday.SAT || day == Weekday.SUN) {
                System.out.println("At home");
            } else {
                System.out.println("At office");
            }
        }
    }

    枚举类是通过关键字enum实现的,我们只需要一次列出枚举的常量名。
    和int定义的常量相比,使用enum定义枚举有如下好处:
      (1)enum常量本身带有类型信息,即Weekday.SUN类型是Weekday,编译器会自动检查类型错误。
      (2)不可能引用到非枚举的值,因为无法通过编译。
      (3)不同类型的枚举不能相互比较或者赋值,因为类型不符。
    这使得编译器可以在编译期自动检查所有可能潜在的错误。

    使用enum定义的枚举是一种引用类型。
    前面我们讲到,引用类型比较,要使用equals()方法,如果使用==,它比较两个引用类型的变量是否是同一个对象。
    因此,引用类型比较,要始终使用equals()方法,但enum类型可以例外。
    因为enum类型的每个常量在JVM中只有一个唯一实例,所以可以直接使用==比较。

    enum定义的枚举类,与class有什么区别了?
    enum是就是一个class,只是被单独定义了。主要区别有以下几点:
      (1)定义的enum类型总是继承自java.lang.Enum,且无法被继承。
      (2)只能定义出enum的实例,无法通过new操作符创建enum对象。
      (3)定义的每个实例都是引用类型的唯一实例
      (4)可以将enum类型用于switch语句。

    例如,我们定义的color类:

    public enum Color {
        RED, GREEN, BLUE;
    }

    编译器编译的class大概就是这样:

    public final class Color extends Enum { // 继承自Enum,标记为final class
        // 每个实例均为全局唯一:
        public static final Color RED = new Color();
        public static final Color GREEN = new Color();
        public static final Color BLUE = new Color();
        // private构造方法,确保外部无法调用new操作符:
        private Color() {}
    }

    所以,编译后的enum类和普通class并没有任何区别。
    但是我们自己无法按定义普通class那样来定义enum关键字,这是Java语法规定。

    因为enum是一个class,每个枚举的值都是class实例,因此,这些实例有一些方法:
    name():返回常量名
      String s = Weekday.SUN.name();
    ordianl():返回定义的常量的顺序,从0开始技术。
      int n = Weekday.MON.ordinal();
    改变枚举常量定义的顺序就会导致ordinal()返回值。

    上面创建的枚举依旧存在一个问题,如果我们不小心修改枚举的顺序,
    那么其所代表的ordinal的返回值也会被修改。
    因为我们可以稍微优化一下,给每个枚举常量添加字段:

    package com.imooc.iexecption;
    
    enum Weekday {
        SUN(0), MON(1),TUE(2),WED(3),THU(4),FRI(5),SAT(6);
    
        public final int dayValue;
    
        private Weekday(int dayValue) {
            this.dayValue = dayValue;
        }
    }
    
    public class catchExample2 {
        public static void main(String[] args) throws Exception {
            Weekday day = Weekday.SUN;
            if (day.dayValue == 6 || day.dayValue == 0) {
                System.out.println("At home");
            } else {
                System.out.println("At office");
            }
        }
    }

    这样,我们就不用过多的关注顺序的问题。
    默认情况下,对枚举常量调用toString()会返回和name()一样的字符串,
    但是,toString()可以被覆写,而name则不行,我们可以给weekday添加toString()方法。

    package com.imooc.iexecption;
    
    enum Weekday {
        SUN(0,"星期日"),
        MON(1,"星期一"),
        TUE(2,"星期二"),
        WED(3,"星期三"),
        THU(4,"星期四"),
        FRI(5,"星期五"),
        SAT(6,"星期六");
    
        public final int dayValue;
        private final String chinese;
    
        private Weekday(int dayValue, String chinese) {
            this.dayValue = dayValue;
            this.chinese = chinese;
        }
        @Override  //不允许被覆写,也可以直接调用name()
        public String toString() {
            return this.chinese;
        }
    }
    
    public class catchExample2 {
        public static void main(String[] args) throws Exception {
            Weekday day = Weekday.SUN;
            if (day.dayValue == 6 || day.dayValue == 0) {
                System.out.println("Today is " + day + " At home");
            } else {
                System.out.println("Today is" + day + "At office");
            }
        }
    }

    覆写toString()的目的是在输出时更有可读性。

    枚举可以应用在switch语句中。因为枚举天生举有类型信息和有限个枚举常量,
    所以比int、String类型更适合用在switch语句中。

    package com.imooc.iexecption;
    
    enum Weekday {
        SUN, MON, TUE, WED, THU, FRI, SAT;
    }
    
    public class catchExample2 {
        public static void main(String[] args) throws Exception {
            Weekday day = Weekday.SUN;
            switch (day) {
                case SUN:
                case MON:
                case THU:
                    System.out.println("Today is " + day + " At home");
                    break;
                case WED:
                case TUE:
                    System.out.println("Today is " + day + " At office");
                    break;
                case FRI:
                case SAT:
                default:
                    throw new RuntimeException("cannot process" + day);
            }
        }
    }

      加上default语句,可以在漏写某个枚举常量时自动报错。

  • 相关阅读:
    ASP.NET HTTP404错误怎么办
    ASP.NET HTTP500错误怎么办
    Fireworks如何制作透明窗口PNG
    CSS如何实现自定义鼠标应用到整个网页
    Dreamweaver如何设置自动换行,修改字体
    火狐浏览器缓存区的利用,如何提取火狐缓存的动画
    PHP快速入门 如何配置Apache服务器
    PHP中调用外部命令的方法
    PHP与SQL数据库交互中文乱码怎么办
    [Angular] Angular Attribute Decorator
  • 原文地址:https://www.cnblogs.com/yangmingxianshen/p/12501447.html
Copyright © 2011-2022 走看看