《Java编程的逻辑》笔记22--枚举的本质

作者: 天一方蓝 | 来源:发表于2019-06-14 09:08 被阅读3次
枚举的本质.png

概念

所谓枚举,是一种特殊的数据,它的取值是有限的,可以枚举出来的, 比如说一年就是有四季、一周有七天,虽然使用类也可以处理这种数据,但枚举类型更为简洁、安全和方便。

基本用法

  • 定义
public enum Size {
    SMALL, MEDIUM, LARGE
}

枚举类型可以定义为一个单独的文件,也可以定义在其他类内部。

  • 使用
Size size = Size.SMALL;
System.out.println(size.toString());
System.out.println(size.name());

输出都是SMALL

Size size = Size.SMALL;
System.out.println(size==Size.SMALL);
System.out.println(size.equals(Size.SMALL));
System.out.println(size==Size.MEDIUM);

分别是true, true, false

Size size = Size.MEDIUM;
System.out.println(size.ordinal());

枚举类型都有一个方法int ordinal(),表示枚举值在声明时的顺序,从0开始

Size size = Size.SMALL;
System.out.println(size.compareTo(Size.MEDIUM));

比较其实就是比较ordinal的大小

static void onChosen(Size size){
    switch(size){
    case SMALL:
        System.out.println("chosen small"); break;
    case MEDIUM:
        System.out.println("chosen medium"); break;
    case LARGE:
        System.out.println("chosen large"); break;
    }
}

在switch语句内部,枚举值不能带枚举类型前缀,例如,直接使用SMALL,不能使用Size.SMALL

for(Size size : Size.values()){
    System.out.println(size);
}

输出为三行,分别是SMALL, MEDIUM, LARGE

枚举的好处

Java是从JDK 5才开始支持枚举的,在此之前,一般是在类中定义静态整形变量来实现类似功能
定义枚举的语法更为简洁。
枚举更为安全,一个枚举类型的变量,它的值要么为null,要么为枚举值之一,不可能为其他值,但使用整形变量,它的值就没有办法强制,值可能就是无效的。
枚举类型自带很多便利方法(如values, valueOf, toString等),易于使用

基本实现原理

枚举类型实际上会被Java编译器转换为一个对应的类,这个类继承了Java API中的java.lang.Enum类

public final class Size extends Enum<Size> {
    public static final Size SMALL = new Size("SMALL",0);
    public static final Size MEDIUM = new Size("MEDIUM",1);
    public static final Size LARGE = new Size("LARGE",2);
    
    private static Size[] VALUES = 
            new Size[]{SMALL,MEDIUM,LARGE};
    
    private Size(String name, int ordinal){
        super(name, ordinal);
    }
    
    public static Size[] values(){
        Size[] values = new Size[VALUES.length];
        System.arraycopy(VALUES, 0, 
                values, 0, VALUES.length);
        return values;
    }
    
    public static Size valueOf(String name){
        return Enum.valueOf(Size.class, name);
    }
}

Size是final的,不能被继承,Enum<Size>表示父类,<Size>是泛型写法,我们后续文章介绍,此处可以忽略。
Size有一个私有的构造方法,接受name和ordinal,传递给父类,私有表示不能在外部创建新的实例。
三个枚举值实际上是三个静态变量,也是final的,不能被修改。
values方法是编译器添加的,内部有一个values数组保持所有枚举值。
valueOf方法调用的是父类的方法,额外传递了参数Size.class,表示类的类型信息,类型信息我们后续文章介绍, 父类实际上是回过头来调用values方法,根据name对比得到对应的枚举值的。
一般枚举变量会被转换为对应的类变量,在switch语句中,枚举值会被转换为其对应的ordinal值。

  • 注意点
    当需要id标记时,最好别用ordinal值

高级用法

枚举类型可以声明抽象方法,每个枚举值中可以实现该方法,也可以重写枚举类型的其他方法。

public enum Size {
    SMALL {
        @Override
        public void onChosen() {
            System.out.println("chosen small");
        }
    },MEDIUM {
        @Override
        public void onChosen() {
            System.out.println("chosen medium");
        }
    },LARGE {
        @Override
        public void onChosen() {
            System.out.println("chosen large"); 
        }
    };
    
    public abstract void onChosen();
}

public enum Size {
    SMALL {
        @Override
        public void onChosen() {
            System.out.println("chosen small");
        }
    },MEDIUM {
        @Override
        public void onChosen() {
            System.out.println("chosen medium");
        }
    },LARGE {
        @Override
        public void onChosen() {
            System.out.println("chosen large"); 
        }
    };
    
    public abstract void onChosen();
}


switch的缺陷是,定义swich的代码和定义枚举类型的代码可能不在一起, 如果新增了枚举值,应该需要同样修改switch代码,但可能会忘记,而如果使用抽象方法,则不可能忘记,在定义枚举值的同时,编译器会强迫同时定义相关行为代码。所以,如果行为代码和枚举值是密切相关的,使用以上写法可以更为简洁、安全、容易维护。

相关文章

  • 《Java编程的逻辑》笔记22--枚举的本质

    概念 所谓枚举,是一种特殊的数据,它的取值是有限的,可以枚举出来的, 比如说一年就是有四季、一周有七天,虽然使用类...

  • 《Java编程的逻辑》笔记 19 - 接口的本质

    概念 很多时候,我们实际上关心的,并不是对象的类型,而是对象的能力 Java使用接口这个概念来表示能力 作用 双方...

  • 《Java编程的逻辑》笔记5-- 循环的本质

    循环的4种形式 while while的语法为: 或 while和if的语法很像,只是把if换成了while,它表...

  • 2019-02-09

    编程语言和非编程语言的本质区别是提供了流程控制语句,有逻辑判断javascript 浏览器端运行php java ...

  • 《Java编程的逻辑》笔记21--内部类的本质

    什么是内部类 个类放在另一个类的内部,称之为内部类 为什么要放到别的类内部呢? 内部类与包含它的外部类有比较密切的...

  • 《Java编程的逻辑》笔记引言

    一丶为什么分享这本书 1.这本书写的好本书从基本概念到高层框架,剖析Java实现原理与JDK源代码,融合专业理论与...

  • 关于Java中枚举Enum的深入剖析

    在编程语言中我们,都会接触到枚举类型,通常我们进行有穷的列举来实现一些限定。Java也不例外。Java中的枚举类型...

  • ##Java学习笔记之基础类库笔记

    Java学习笔记之基础类库笔记 Object 所有类,数组,枚举类的父类 Objects(Java7新增) 工具类...

  • 一些开发规范

    编程规范 防御式编程,根据有限枚举先处理断言,再处理错误,最后处理正常逻辑,正常逻辑外尽可能多的处理异常分支;开发...

  • Java编程的逻辑

    零 概述 本篇文章是读《Java编程逻辑》的笔记 第一部分 编程基础与二进制 第1章 编程基础 为了操作数据方便,...

网友评论

    本文标题:《Java编程的逻辑》笔记22--枚举的本质

    本文链接:https://www.haomeiwen.com/subject/zzpdfctx.html