目录
Java编程思想(一)第1~4章:概述
Java编程思想(二)第5章:初始化和清理
Java编程思想(三)第6章:访问权限
Java编程思想(四)第7章:复用类
Java编程思想(五)第8章:多态
Java编程思想(六)第9章:接口
Java编程思想(七)第10章:内部类
Java编程思想(八)第11章:持有对象
Java编程思想(九)第12章:异常
Java编程思想(十)第13章:字符串
Java编程思想(十一)第14章:类型信息
Java编程思想(十二)第15章:泛型
Java编程思想(十三)第16章:数组
Java编程思想(十四)第17章:深入研究容器
Java编程思想(十五)第18章:Java I/O系统
Java编程思想(十六)第19章:枚举
Java编程思想(十七)第20章:注解
Java编程思想(十八)第21章:并发

第十九章、枚举类型

目录

1. 基本enum特性

2. switch语句中的enum

3.values()的神秘之处

5. 实现,而非继承

6. 随机选取

7. 使用接口组织枚举

8. 使用EnumSet替代位标志(BitSet)

9. 使用EnumMap

10 常量相关的方法

11 多路分发


概述:

  • 关键字enum:可以将一组具名的值的有限集合创建为一种新的类型(Class),而这些具名的值可以作为常规的程序组件使用。
  • 创建enum时,编译器会为你自动生成一个相关类,此类自动extends java.lang.Enum类。

1. 基本enum特性

Enum类提供的功能如下:

  • values() 返回enum实例的数组,而且保持声明的顺序:
  • ordinal() 返回一个int值,这是每个enum实例在声明时的次序,从0开始。
  • == 来比较enum实例,编译器会自动提供equals和hashCode方法。
  • getDeclaringClass() 获取其所属的enum类。
  • name() 返回enum实例声明时的名字,与使用toString()效果相同。
  • Enum.valueOf() 是在Enum中定义的static方法,他根据给定的名字返回相应的enum实例,如果不存在会抛出异常。

1.1 将静态导入用于enum

  • 使用static import能够将enum实例的标识符代入当前的命名空间,所以无需再用enum类型来修饰enum实例。
  • 唯一担心的是使用静态导入会不会导致代码令人难以理解。

import static enumerated.Spiciness*;

1.2 向enum中添加新方法

  • 除了不能继承自一个enum之外,基本上可以将enum看做一个常规类。
  • 也就是说,可以添加方法,甚至可以有main方法。
  • 必须先定义enum实例,如果在实例之前定义任何方法或属性,编译时会报错。
  • 一旦enum的定义结束,编译器就不允许在使用其构造器来创建任何实例了。
public enum OzWitch {// Instances must be defined first, before methods: WEST("Miss Gulch"),NORTH("Glinda"),EAST("Wicked"),SOUTH("Good");//必须在enum实例序列的最后添加一个分号。private String description;// Constructor must be package or private access:private OzWitch(String description) {this.description = description;}public String getDescription() {return description;}@Override public String toString() {}public static void main(String[] args) {for (OzWitch witch : OzWitch.values()) {print(witch + ": " + witch.getDescription());}}
}

2. switch语句中的enum

  • 一般来说switch中只能使用整形值;
  • 而枚举类型天生就具备整形值的次序,并且可以通过ordinal()方法获取其次序。
enum Signal {GREEN, YELLOW, RED,
}
public class TrafficLight {Signal color = Signal.RED;public void change() {switch (color) {case RED:case GREEN:case YELLOW:}}
}

3.values()的神秘之处

enum类都自动继承自Enum类(编译器实现),我们可以查看Enum中并没有values()方法。利用反射机制查看究竟:

  • values()是由编译器自动添加的static方法。同时创建Explore的过程中,编译器还添加了valueOf()方法。不是Enum类已经有valueOf()方法了吗,不过Enum中的ValueOf()方法需要两个参数,这个新增方法只需一个参数。由于Set只存储方法的名字,不考虑签名,所以removeAll只剩下values。
  • 由于values()方法有编译器插入到enum定义中的static方法,所以enum向上转型为Enum,那么values就不可访问了,不过Class中有一个getEnumConstants方法,所以即便Enum接口中没有vlaues方法,仍然可以通过Class对象取得所有enum实例:
enum Search {HITHER, YON}public class UpcastEnum {public static void main(String[] args) {Search[] vals = Search.values();Enum e = Search.HITHER; // Upcast// e.values(); // No values() in Enumfor (Enum en : e.getClass().getEnumConstants()) {System.out.println(en);}}
} getEnumConstants() 获取所有Enum对象的实例

5. 实现,而非继承

  • 不能extends:Java不支持多重继承;并编译器自动extends了Enum类了;
  • 可以implements:创建一个新的enum,可以同时实现一个或多个接口。
enum CartoonCharacter implements Generator<CartoonCharacter> {SLAPPY, SPANKY, PUNCHY, SILLY, BOUNCY, NUTTY, BOB;private Random rand = new Random(47);@Overridepublic CartoonCharacter next() {return values()[rand.nextInt(values().length)];}
} 

6. 随机选取

7. 使用接口组织枚举

  • 子类化:implements是enum 子类化的唯一方法。
  • 有时希望使用子类将一个enum中的元素进行分组。在一个接口内部创建实现该接口的枚举,以此将元素分组。
public interface Food {enum Appetizer implements Food {SALAD, SOUP, SPRING_ROLLS;}enum MainCourse implements Food {LASAGNE, BURRITO, PAD_THAI,LENTILS, HUMMOUS, VINDALOO;}enum Dessert implements Food {TIRAMISU, GELATO, BLACK_FOREST_CAKE,FRUIT, CREME_CARAMEL;}enum Coffee implements Food {BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,LATTE, CAPPUCCINO, TEA, HERB_TEA;}
}public class TypeOfFood {public static void main(String[] args) {Food food = Appetizer.SALAD;food = MainCourse.LASAGNE;food = Dessert.GELATO;food = Coffee.CAPPUCCINO;}
}

8. 使用EnumSet替代位标志(BitSet)

  • Set:是一种集合不能添加重复元素。enum也要求其成员是唯一的。
  • EnumSet:Java SE5引入了EnumSet,是为了通过enum创建一种替代品,以替代传统的基于int的“位标志”(BitSet)。这种标志可以用来表示某种开关信息,不过,使用这种标志,最终操作的只是一些bit。
  • EnumSet的性能:它在说明一个二进制位是否存在时,具有更好的表达能力,并且无需担心性能。

EnumSet 包含的使用方法:

  • EnumSet.noneOf(AlarmPoints.class); 返回Empty set
  • EnumSet.complementOf() 用于创建包含与指定的Enum_Set类型相同的元素的EnumSet
  • EnumSet.of() 返回参数中添加的Enum元素集合
  • EnumSet.range() 返回参数中指定范围的Enum元素
  • points.addAll() 添加所有Enum元素
  • points.removeAl() 移除参数中包含的Enum元素集合

研究EnumSet文档,会发现of()方法被重载了很多次,不但为可变数量参数进行了重载,而且为接受2至5个显式的参数的情况都进行了重载。这也从侧面表现了EnumSet对性能的关注。

9. 使用EnumMap

  • EnumMap:是一种特殊的Map(Key-Value映射表),要求其中的键(key)必须来自于一个enum。
  • EnumMap的性能:由于enum本身的限制,所以EnumMap内部是数组实现。因此EnumMap速度很快,可以放心进行查找操作。
  • EnumMap的排序:与EnumSet一样,enum实例(key)定义时的次序决定了其在EnumMap中的顺序。

9.1 命令模式(GoF23之一)的具体实现

interface Command { void action();
}
enum AlarmPoints{ STAIR,LOBBY,OFFICE,BATHROOM,UTILITY,KITCHEN
}
public class EnumMaps {public static void main(String[] args) {EnumMap<AlarmPoints, Command> em = new EnumMap<AlarmPoints, Command>(AlarmPoints.class);em.put(KITCHEN, new Command() {public void action() {print("Kitchen fire!");}});em.put(BATHROOM, new Command() {public void action() {print("Bathroom alert!");}});for (Map.Entry<AlarmPoints, Command> e : em.entrySet()) {printnb(e.getKey() + ": ");e.getValue().action();}try { // If there's no value for a particular key:em.get(UTILITY).action();} catch (Exception e) {print(e);}}
}

9.2 EnumMap 包含的使用方法:

  • put(k,v) 新增元素(k,v)
  • get(k) 返回参数k对应的value
  • entrySet() 返回<k,v>实例对象集合
  • Map.Entry<K,V>.getValue() 返回实例元素的value

10 常量相关的方法

  • 常量相关的方法:constant-specific methods
  • 多路分发:multiple dispatching
  • 枚举元素:在Enum中定义的元素都是Enum类中的各个实例对象,每个Enum元素都是一个Enum类型的staic final类型对象。
  • 常量相关的方法的enum实现方式:enum 允许为每个enum实例(枚举元素)编写方法,从而为每个enum实例赋予各自不同的行为,从而为每个enum实例赋予各自不同的行为。
public enum ConstantSpecificMethod {DATE_TIME {String getInfo() {return  DateFormat.getDateInstance().format(new Date());}},CLASSPATH {String getInfo() {return System.getenv("CLASSPATH");}},VERSION {String getInfo() {return System.getProperty("java.version");}};abstract String getInfo();public static void main(String[] args) {for (ConstantSpecificMethod csm : values()) {System.out.println(csm.getInfo());}}
}

10.1 使用enum的职责链

  • 职责链模式:(Chain of Responsibility,GoF23设计模式之一):程序员以多种不同的方式来解决一个问题,然后将它们链接在一起。当请求到来时,它遍历这个链,直到这个链中的某个解决方案能够处理此需求。
  • 代码示例 参照原文P607

10.2 使用enum的状态机

  • 状态机模式:(GoF23设计模式之一):一个状态机可以具有有限个特定的状态,它通常根据输入,从一个状态转移到下个状态,不过也可能存在瞬时状态(transient states),而一旦任务执行结束,状态机会立即离开瞬时状态。
  • 瞬时状态:(transient states):
  • 代码示例 参照原文P609

11 多路分发

  • 单路分发:Java只支持单路分发:如果要执行的操作包含了不只一个类型未知的对象时,java的动态绑定机制只能处理其中一个的类型。
  • 多路分发:含二路分发。

多路分发的几种实现方式:

  • 使用enum分发:
  • 使用常量相关的方法分发
  • 使用EnumMap分发
  • 使用二维数组

《JAVA编程思想》学习笔记:第19章(枚举)相关推荐

  1. Java编程思想学习笔记-第11章

    <?xml version="1.0" encoding="utf-8"?> Java编程思想学习笔记-第11章 Java编程思想学习笔记-第11章 ...

  2. JAVA编程思想学习笔记——第一章 对象导论

    搞了一年多java,野路子出身,发现java基础这块还是相当的薄弱!故决定学习<Java编程思想>这本书.在此把学习的知识点记录下! 面向对象的五大特性 1.万物皆为对象 2.程序是对象的 ...

  3. Java编程思想学习笔记4 - 序列化技术

    今天来学习下Java序列化和反序列化技术,笔者对<Java编程思想>中的内容,结合网上各位前辈的帖子进行了整理和补充,包括: 序列化概述 Java原生序列化技术 Hessian序列化技术 ...

  4. java编程思想学习笔记(第七章:复用类)

    复用代码是java众多引人注目的功能之一.但是要想成为极具革命性的语言,仅仅能够复制代码并对之加以改变是不够的,它还必须能够做更多的事情. 7.1组合语法 将对象引用置于新类中.每一个非基本类型的对象 ...

  5. Java编程思想 学习笔记1

    一.对象导论 1.抽象过程 Alan Kay曾经总结了第一个成功的面向对象语言.同时也是Java所基于的语言之一的Smalltalk的五个基本特性,这些特性表现了纯粹的面向对象程序设计方式 1)万物皆 ...

  6. java编程思想 学习笔记(2)

    第二章     一切都是对象 用引用(reference)操纵对象 String s = "asdf"; String s; 但这里所创建的只是引用,并不是对象.如果此时向s 发送 ...

  7. Java编程思想读书笔记——第七章:复用类

    第七章 复用类 使用类而不破坏现有程序代码,有两种达到这一目的的方法: 在新的类中产生现有类的对象,也就是说new一个对象,这种方法称为组合 按照现有类的类型来创建新类,不改变现有类的形式,在其基础上 ...

  8. Java编程思想 学习笔记7

    七.复用类 1.组合语法 在新的类中产生现有类的对象.由于新的类是由现有类的对象所组成,所以这种方法叫做组合. 类中域为基本类型时能够自动被初始化为零.对象引用被初始化为null. 编译器不是简单地为 ...

  9. Java编程思想读书笔记--第21章并发

    1.基本的线程机制 定义任务 public class LiftOff implements Runnable{protected int countDown = 10;private static ...

  10. Python快速编程入门#学习笔记01# |第一章 :Python基础知识 (Python发展历程、常见的开发工具、import模块导入)

    全文目录 ==先导知识== 1 认识Python 1.1.1 Python的发展历程 1.1.2 Python语言的特点 2. Python解释器的安装与Python程序运行 1.2.1 安装Pyth ...

最新文章

  1. css 子元素设置float,父元素高度塌陷
  2. 干货满满的 Python 实战项目,点赞收藏
  3. Java IO: 管道
  4. 企业架构 - 组织角色和技能
  5. iOS学习笔记(1)--认识Xcode6.1的Interface Builder和常用快捷键
  6. Scrapy学习-24-集成elasticsearch
  7. 【LeetCode笔记】剑指 Offer 47. 礼物的最大价值(Java、动态规划)
  8. docbook_DocBook简介,一种值得学习的灵活标记语言
  9. jdbctemplate 执行多条sql_白帽推荐:可以自动检索、挖掘sql注入的神器,sqlmap入门实战
  10. 学web前端开发写给新手的建议,超实用
  11. #pragma comment使用
  12. android 盒子刷机,刷机精灵 – 最好用的Android刷机工具
  13. C语言程序设计 | 猜数字游戏
  14. 计算机网络毕业论文格式模板范文,计算机网络论文范文 计算机网络方面有关毕业论文的格式范文2万字...
  15. C++(2-4)——sqrt的使用
  16. dockerfile使用DEBIAN_FRONTEND
  17. 网易游戏大咖分享——游戏行业职位发展(上)
  18. 假定在使用CSMA/CD协议的10Mbit/s以太网中某个站在发送数据时检测到碰撞,执行退避算法时选择了随机数r=100.试问这个站需要等待多长时间后才能再次发送数据?如果是100Mbit/s的以太网
  19. java8 stream运行原理之并行流原理详解
  20. 输入框限制不允许输入中文

热门文章

  1. 黑马头条移动端接口丨跨域丨踩坑
  2. c语言课程设计计算器软件,C语言课程设计简单计算器程序.docx
  3. DIP数字图像处理-知识提纲
  4. Hexo yilia 主题添加相册功能
  5. ClsName2id.txt
  6. vscod边调试html,答应你们的VSCO手机调色教程第二弹来啦~最近发的一些照片用了下面...
  7. UE5使用DLSS(超级采样)提升场景的 FPS 远离卡顿的优化方案
  8. 阿里年薪百万架构师分享「亿级并发系统架构设计」全彩版技术手册,只能说其实高并发不难
  9. Functions are not valid as a React child. This may happen if you return a Component instead of
  10. BeautifulReport测试报告的bootstrap文件失效(404)