Tips

《Effective Java, Third Edition》一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化。

在这里第一时间翻译成中文版。供大家学习分享之用。

36. 使用EnumSet替代位属性

如果枚举类型的元素主要用于集合中,一般来说使用int枚举模式(条目 34),下面将2的不同倍数赋值给每个常量:

// Bit field enumeration constants - OBSOLETE!
public class Text {
public static final int STYLE_BOLD = 1 << 0; // 1
public static final int STYLE_ITALIC = 1 << 1; // 2
public static final int STYLE_UNDERLINE = 1 << 2; // 4
public static final int STYLE_STRIKETHROUGH = 1 << 3; // 8 // Parameter is bitwise OR of zero or more STYLE_ constants
public void applyStyles(int styles) { ... }
}

这种表示方式允许你使用按位或(or)运算将几个常量合并到一个称为位属性(bit field)的集合中:

text.applyStyles(STYLE_BOLD | STYLE_ITALIC);

位属性表示还允许你使用按位算术有效地执行集合运算,如并集和交集。 但是位属性具有int枚举常量等的所有缺点。 当打印为数字时,解释位属性比简单的int枚举常量更难理解。 没有简单的方法遍历所有由位属性表示的元素。 最后,必须预测在编写API时需要的最大位数,并相应地为位属性(通常为int或long)选择一种类型。 一旦你选择了一个类型,你就不能超过它的宽度(32或64位)而不改变API。

一些程序员使用枚举优于int常量,当他们需要传递常量集合时仍然使用位属性。 没有理由这样做,因为存在更好的选择。 java.util包提供了EnumSet类来有效地表示从单个枚举类型中提取的值集合。 这个类实现了Set接口,提供了所有其他Set实现的丰富性,类型安全性和互操作性。 但是在内部,每个EnumSet都表示为一个位矢量(bit vector)。 如果底层的枚举类型有64个或更少的元素,并且大多数情况下,整个EnumSet用单个long表示,所以它的性能与位属性的性能相当。 批量操作(如removeAll和retainAll)是使用按位算术实现的,就像你为位属性手动操作一样。 但是完全避免了手动位混乱的丑陋和错误倾向:EnumSet为你做了很大的努力。

下面是前一个使用枚举和枚举集合替代位属性的示例。 它更短,更清晰,更安全:

// EnumSet - a modern replacement for bit fields
public class Text {
public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH } // Any Set could be passed in, but EnumSet is clearly best
public void applyStyles(Set<Style> styles) { ... }
}

这里是将EnumSet实例传递给applyStyles方法的客户端代码。 EnumSet类提供了一组丰富的静态工厂,可以轻松创建集合,其中一个代码如下所示:

text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));

请注意,applyStyles方法采用Set<Style>而不是EnumSet<Style>参数。 尽管所有客户端都可能会将EnumSet传递给该方法,但接受接口类型而不是实现类型通常是很好的做法(条目 64)。 这允许一个不寻常的客户端通过其他Set实现的可能性。

总之,仅仅因为枚举类型将被用于集合中,所以没有理由用位属性来表示它EnumSet类将位属性的简洁性和性能与条目 34中所述的枚举类型的所有优点相结合。EnumSet的一个真正缺点是,它不像Java 9那样创建一个不可变的EnumSet,但是在即将发布的版本中可能会得到补救。 同时,你可以用Collections.unmodifiableSet封装一个EnumSet,但是简洁性和性能会受到影响。

Effective Java 第三版——36. 使用EnumSet替代位属性的更多相关文章

  1. Effective Java 第三版——37. 使用EnumMap替代序数索引

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  2. 《Effective Java 第三版》目录汇总

    经过反复不断的拖延和坚持,所有条目已经翻译完成,供大家分享学习.时间有限,个别地方翻译得比较仓促,希望有疑虑的地方指出批评改正. 第一章简介 忽略 第二章 创建和销毁对象 1. 考虑使用静态工厂方法替 ...

  3. 《Effective Java 第三版》新条目介绍

    版权声明:本文为博主原创文章,可以随意转载,不过请加上原文链接. https://blog.csdn.net/u014717036/article/details/80588806前言 从去年的3月份 ...

  4. Effective Java 第三版——1. 考虑使用静态工厂方法替代构造方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  5. Effective Java 第三版——32.合理地结合泛型和可变参数

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  6. Effective Java 第三版——46. 优先考虑流中无副作用的函数

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  7. Effective Java第三版(一) ——用静态工厂代替构造器

    此文做为<Effective Java>系列的第一篇,所以有必要大概说下此书的特点,当然很多人可能都看过,毕竟是有着Java四大名著之一的大名在外,不过总会有萌新不了解,例如我!<E ...

  8. Effective Java 第三版——3. 使用私有构造方法或枚类实现Singleton属性

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  9. Effective Java 第三版——7. 消除过期的对象引用

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

随机推荐

  1. binlog和redo log日志提交

    组提交(group commit)是MYSQL处理日志的一种优化方式,主要为了解决写日志时频繁刷磁盘的问题.组提交伴随着MYSQL的发展不断优化,从最初只支持redo log 组提交,到目前5.6官方 ...

  2. Codeforces Round #437 (Div. 2, based on MemSQL Start[c]UP 3.0 - Round 2)

    Problem A Between the Offices 水题,水一水. #include<bits/stdc++.h> using namespace std; int n; ]; i ...

  3. BZOJ1177 [Apio2009]Oil 二维前缀和 二维前缀最值

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1177 题意概括 在一个n*m的矩阵中,每一个位置一个数字. 现在让你选出3个k*k的矩阵,它们互不 ...

  4. spring继承Rabbitmq client-----------------------待研究

    一:概述 1.官网 https://spring.io/ 2.进入project 3.找到spring AMQP 二:程序 1.结构 2.pom <?xml version="1.0& ...

  5. java爬虫抓取腾讯漫画评论

    package com.eteclab.wodm.utils; import java.io.BufferedWriter; import java.io.File; import java.io.F ...

  6. java 如何用pattern 和 Matcher 来使用正则表达式

    java的regex库 java里预留了一个regex库,方便于我们在java里操作正则表达式,或者用它来匹配字符串. 其中比较常用的就是 Pattern 和 Matcher ,pattern是一个编 ...

  7. python tkinter-消息框、对话框、文件对话框

    python tkinter-消息框.对话框.文件对话框   消息框 导入 import tkinter import tkinter.messagebox #这个是消息框,对话框的关键 提示消息框 ...

  8. xss总结--2018自我整理

    0x00前言 因为ctf中xss的题目偏少(因为需要机器人在后台点选手的连接2333),所有写的比较少 这里推荐个环境http://test.xss.tv/ 0x01xss作用 常见的输出函数:pri ...

  9. u3d 鼠标点击位置,物体移动过去。 U3d mouse clicks position, objects move past.

    u3d 鼠标点击位置,物体移动过去. U3d mouse clicks position, objects move past. 作者:韩梦飞沙 Author:han_meng_fei_sha 邮箱: ...

  10. BZOJ.1901.Dynamic Rankings(线段树套平衡树 Splay)

    题目链接or Here 题意:n个数,有两个操作:1.修改某个数为v:2.询问一段区间第k小的数 如果没有修改,则可以用线段树,每个节点P[a,b]存储大小为b-a+1的数组,代表其中的数 同时,这个 ...