Effective Java 2 读书笔记 第6章 枚举和注解
编程技术  /  houtizong 发布于 3年前   98
枚举类型对比int枚举,String枚举等
可以将数据与枚举常量关联起来,得声明实例域,并编写一个带有数据并将数据保存在域中的构造器
可以将不同行为与每个枚举常量关联起来,特定于常量的类主体
如果多个枚举常量同时共享相同的行为,则考虑策略枚举,而不是switch
枚举中的switch语句适合于给外部的枚举类型增加特定于常量的行为。如针对Operation的每个操作返回相反的操作
// Enum type with constant-specific method implementationspublic enum Operation {PLUS { double apply(double x, double y){return x + y;} },MINUS { double apply(double x, double y){return x - y;} },TIMES { double apply(double x, double y){return x * y;} },DIVIDE { double apply(double x, double y){return x / y;} };abstract double apply(double x, double y);}
永远不要根据枚举的序数导出与它关联的值,而是要将它保存在一个实例域中。
// Abuse of ordinal to derive an associated value - DON'T DO THISpublic enum Ensemble {SOLO, DUET, TRIO, QUARTET, QUINTET,SEXTET, SEPTET, OCTET, NONET, DECTET;public int numberOfMusicians() { return ordinal() + 1; }}
应该这样用,比较好
public enum Ensemble {SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUINTET(5),SEXTET(6), SEPTET(7), OCTET(8), DOUBLE_QUARTET(8),NONET(9), DECTET(10), TRIPLE_QUARTET(12);private final int numberOfMusicians;Ensemble(int size) { this.numberOfMusicians = size; }public int numberOfMusicians() { return numberOfMusicians; }}
EnumSet可以代替位算法来传递丰富的参数,如下例子用EnumSet来设置Text的style
// EnumSet - a modern replacement for bit fieldspublic class Text {public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH }// Any Set could be passed in, but EnumSet is clearly bestpublic void applyStyles(Set<Style> styles) { ... }}将EnumSet实力传递给applyStyle这个方法的接口参数text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));
总结:正式因为枚举类型要用在集合(Set)中,所以没有理由用位域来表示它。
有时候会看见用ordinal方法来索引数组的代码,如:
public class Herb {public enum Type { ANNUAL, PERENNIAL, BIENNIAL }private final String name;private final Type type; Herb(String name, Type type) {this.name = name;this.type = type;}@Override public String toString() {return name;}}// Using ordinal() to index an array - DON'T DO THIS!Herb[] garden = ... ;Set<Herb>[] herbsByType = // Indexed by Herb.Type.ordinal()(Set<Herb>[]) new Set[Herb.Type.values().length];for (int i = 0; i < herbsByType.length; i++)herbsByType[i] = new HashSet<Herb>();for (Herb h : garden)herbsByType[h.type.ordinal()].add(h);// Print the resultsfor (int i = 0; i < herbsByType.length; i++) {System.out.printf("%s: %s%n",Herb.Type.values()[i], herbsByType[i]);}
这种方法虽然的确可行,但是隐藏这许多问题,数组不知道它的索引代表着什么,你必须手工标注这些索引的输出。但是按照枚举的顺序进行索引数组的时候,int不能提供枚举的类型安全。
这时候需要使用EnumMap,快速实现枚举值映射
// Using an EnumMap to associate data with an enumMap<Herb.Type, Set<Herb>> herbsByType =new EnumMap<Herb.Type, Set<Herb>>(Herb.Type.class);for (Herb.Type t : Herb.Type.values())herbsByType.put(t, new HashSet<Herb>());for (Herb h : garden)herbsByType.get(h.type).add(h);System.out.println(herbsByType);
同样进行多次索引(数组的数组),道理是一样的
总而言之,最好要用序数来索引数组,而要是有EnumMap。
多维的汝EnumMap<..., EnumMap<...>>
虽然无法编写可扩展的枚举类型,却可以通过编写接口以及实现该接口的基础枚举类型,对它进行模拟。
如对于操作Operation,在基本操作枚举已有的情况下,假如需要添加更多的操作,可以编写扩展的枚举来实现这个接口,针对基础枚举的API是根据接口来编写的,对扩展的枚举同样适用。
基础的Operation
// Emulated extensible enum using an interfacepublic interface Operation {double apply(double x, double y);}public enum BasicOperation implements Operation {PLUS("+") {public double apply(double x, double y) { return x + y; }},MINUS("-") {public double apply(double x, double y) { return x - y; }},TIMES("*") {public double apply(double x, double y) { return x * y; }},DIVIDE("/") {public double apply(double x, double y) { return x / y; }};private final String symbol;BasicOperation(String symbol) {this.symbol = symbol;}@Override public String toString() {return symbol;}}
扩展的Operation
// Emulated extension enumpublic enum ExtendedOperation implements Operation { EXP("^") { public double apply(double x, double y) { return Math.pow(x, y); } }, REMAINDER("%") { public double apply(double x, double y) { return x % y; } }; private final String symbol; ExtendedOperation(String symbol) { this.symbol = symbol; } @Override public String toString() { return symbol; }}
目前使用很少,没有什么深刻体会,理解不透
在你想要覆盖超类声明的每个方法中声明使用Override注解,这样编译器就会帮助你发现是否正确覆盖了一个方法。
例外:在具体的类中,不必标注你确信覆盖了的抽象的方法;实现接口的类中,也不必标注出你想要哪些方法来覆盖接口方法,这两种情况编译器都会帮助你提醒,没有覆盖,抛出错误。当然标注了也没有什么坏处。
但是在抽象类和接口覆盖超类或者超接口的时候,坚持使用Override注解
不知所云
上一条:Effective Java 2 读书笔记 第6章 枚举和注解
请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!
技术博客集 - 网站简介:
前后端技术:
后端基于Hyperf2.1框架开发,前端使用Bootstrap可视化布局系统生成
网站主要作用:
1.编程技术分享及讨论交流,内置聊天系统;
2.测试交流框架问题,比如:Hyperf、Laravel、TP、beego;
3.本站数据是基于大数据采集等爬虫技术为基础助力分享知识,如有侵权请发邮件到站长邮箱,站长会尽快处理;
4.站长邮箱:[email protected];
文章归档
文章标签
友情链接