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. MySQL普通用户无法本地登录的解决方法及MySQL的用户认证算法

    在安装完成MySQL后,我们通常添加拥有相应权限的普通用户用来访问数据库.在使用普通用户本地登录数据库的时候,经常会出现怎么登录也无法登录的情况. 例如,我的MySQL中的用户为: mysql> ...

  2. macos 下安装virtualenv,virtualenvwrapper,然后在pycharm中正常配置方法日志

    1.安装virtualenv或virtualenvwrapper pip install virtualenv pip install virtualenvwraper 注意pip的版本号(查看 pi ...

  3. 如何下载离线Adobe软件教程

    在如今好多软件官网上面都不支持离线安装包下载,仅仅只留下一个在线安装,那么面对这种情况我们应该如何去做?在这里我先提供一个常用的PDF阅读器离线安装包下载地址,在文章后面会有教程. Adobe Acr ...

  4. UC浏览器中Ajax请求中传递数据的一个坑

    今天突然收到一个bug,有用户在其浏览器环境中一直无法提交内容,使用的是UC浏览器.当换成Chrome时,内容能够正常提交.鉴于本地没有一直使用Firefox 以及Chrome,于是去下载了一个UC ...

  5. html/css实现阴影蒙版覆盖原网页并显示浮框的功能

    在提供用户修改资料/密码等功能的时候,往往希望给用户这样的使用体验,在不跳转,不弹框的情况下完成对这些功能的操作. 这可以通过一种效果来实现,在同一页面下阴影覆盖整个当前网页并使得原网页中元素无法使用 ...

  6. django-用户验证系统

    django提供了一套用户验证系统,但是要使用这个系统,必须要使用django内置的用户模型:django.contrib.auth.models.User,这个模型中预先定义了一些字段,其中只有us ...

  7. 2016年3月11日Android实习日记

    1.明天删除orthodotics_design_animation_content_gif.gif文件.(已完成) 2. 如何检测内存泄露? A: 可以通过一些性能监测分析工具,如 JProfile ...

  8. 107. 二叉树的层次遍历 II

    107. 二叉树的层次遍历 II 题意 给定一个二叉树,返回其节点值自底向上的层次遍历. (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历). 解题思路 递归:利用前序遍历的思想,在递归过程中 ...

  9. 使用 SHOW STATUS 查看mysql 服务器状态信息

    在LAMP架构的网站开发过程中,有些时候我们需要了解MySQL的服务器状态信息,譬如当前MySQL启动后的运行时间,当前MySQL的客户端会话连接数,当前MySQL服务器执行的慢查询数,当前MySQL ...

  10. Windows平台交叉编译Arm Linux平台的QT5.7库

    1.准备交叉编译环境 环境说明:Windows 7 64位 此过程需要: (1)Qt库开源代码,我使用的是5.7.0版本: (2)Perl语言环境5.12版本以上: (3)Python语言环境 2.7 ...