博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Effective Java 阅读笔记——枚举和注解
阅读量:4315 次
发布时间:2019-06-06

本文共 2929 字,大约阅读时间需要 9 分钟。

30:用enum代替int常量

当需要一组固定常量的时候,应该使用enum代替int常量,除了对于手机登资源有限的设备应该酌情考虑enum的性能弱势之外。

31:用实例域代替序数

应该给enum添加int域,而不是使用ordinal方法来导出与枚举关联的序数值。(几乎不应使用ordinal方法,除非在编写像EnumMap这样的基于枚举的通用数据结构)

//WRONGpublic enum Fruit{    APPLE, PEAR, ORANGE;    public int numberOfFruit(){        return ordinal() + 1;   }}//RIGHTpublic enum Fruit{    APPLE(1), PEAR(2), ORANGE(3);    private final int number;    Fruit(int num) {number  = num;}    public int numberOfFruit(){        return number;    }}

32:用EnumSet代替位域

EnumSet的内容都表示为位矢量。如若底层的枚举类型个数小于64个,则整个EnumSet就用单个long来表示,因此性能上比的上位域。

//WRONGpublic class Text{    private static final int STYLE_BOLD                  = 1 << 0;    private static final int STYLE_ITALIC                 = 1 << 1;    private static final int STYLE_UNDERLINE         = 1 << 2;    public void applyStyles(int styles) {...}}//usetext.applyStyles(STYLE_BOLD | STYLE_ITALIC);//RIGHTpublic class Text{    public enum Style{STYLE_BOLD, STYLE_ITALIC, STYLE_UNDERLINE}    public void applyStyles(Set

 

33:用EnumMap代替序数索引

序数索引是指依赖于枚举成员在枚举中的序数来进行数组索引,如:

//定义了植物类,其中植物又分为水果,蔬菜,树木三种public class Plant{    public enum Type { Fruit, Vegetables, Tree}    private final String name;    private final Type type;    Plant(String name, Type type){        this.name = name;        this.type = type;    }}Set
[] plants = (Set
[]) new Set[Plant.Type.valuse().lenght]; //根据植物的类型,分别把所有的植物放入三个set中for(int i = 0; i < plant.lenght; i++){ plant[i] = new HashSet
();}for(Plant p : garden){ //garden里放了所有的植物 plant[p.type.ordinal()].add(p) //反面教材:利用了枚举的序数来得到想要的数组索引,用户在其他地方可以不使用ordinal函数,而直接使用int值来访问,就可能出错}

应该使用EnumMap来实现,EnumMap内部是采用数组实现的,具有Map的丰富功能和类型安全以及数组 的效率:

Map
> plants = new EnumMap
>(Plant.Type.class); //构造函数需要 键 类型的Class对象//根据植物的类型,分别把所有的植物放入三个set中for(Plant.Type type : Plant.Type.valuse()){ plant.put(type, new HashSet
);}for(Plant p : garden){ //garden里放了所有的植物 plant.get(p.type).add(p) //用户必须使用正确的键值来访问,即Type类型}

当需要多维关系时,可以使用EnumMap<..., EnumMap<...>>

34:用接口模拟可以伸缩的枚举

由于在java中enum不是可扩展的,在某些情况下,可能需要对枚举进行扩展,比如操作类型(+-*/等),就可以考虑:

  1. 定义一个接口,比如public interface Operation{...};
  2. 使枚举继承接口:比如public enum BasicOperation implements Operation{...}
  3. 使用时的API写成接口(比如,T extends Enum<T> & Operation),而不是实现(比如BasicOperation )
    private static 
    & Operation> void function(T t,..); //表示T即表示枚举又是Operation的子类型

     

  4. 当需要扩展BasicOperation枚举时,就可以另写一个枚举,且implements接口Operation

35:注解优先于命名模式

优先使用注解来表面针对某些程序元素的特定信息

36:坚持使用Override注解

在想要覆盖的方法上使用Override注解,编译器就可以帮助发现一些错误。可以不写Override的特例:在非抽象类中实现了父类的抽象方法,因为要是没有覆盖,则编译器就会发出错误。

37:用标记接口实现类型

标记分为标记接口和标记注解。

标记接口:没有包含方法声明的接口,只是指明某个类实现了具有某种属性的接口。比如Serializable接口。

标记接口与标记注解的最终要的区别在于:标记接口可以在编译时就检查到相应的类型问题,而标记注解则要到运行时。

使用:当标记要应用到任何程序元素,包括方法、域等,而不仅仅是接口和类,或者在未来会给标注添加更多信息,或者要适应已经广泛使用注解类型的框架,那么应该使用标记注解;当标记只应用给类和接口,定义一个任何新方法都不会与之关联的标记类型,就应该使用标记接口。

转载于:https://www.cnblogs.com/willhua/p/5116625.html

你可能感兴趣的文章
C# MySql 连接
查看>>
网络抓包分析方法大全
查看>>
sql 数据类型
查看>>
android 截图
查看>>
WebServicer接口类生成方法。
查看>>
POJ 1740
查看>>
【翻译】火影忍者鸣人 疾风传 终级风暴2 制作介绍
查看>>
http和webservice
查看>>
hdu1879------------prim算法模板
查看>>
jdbc之二:DAO模式
查看>>
MySQL性能优化方法一:缓存参数优化
查看>>
Angular2 - 概述
查看>>
正则表达式tab表示\t
查看>>
NodeJS+Express+MongoDB 简单实现数据录入及回显展示【Study笔记】
查看>>
Highcharts使用指南
查看>>
网络基础(子网划分)
查看>>
Google C++ Style
查看>>
MyBatis总结八:缓存介绍(一级缓存,二级缓存)
查看>>
div+css教程网站建设门户网站和电子商务网站CSS样式表
查看>>
[LeetCode][JavaScript]Candy
查看>>