Effective Java:善于使用枚举(enum)和注解(annotation)
来源:互联网 发布:彩票 java编程 面试题 编辑:程序博客网 时间:2024/06/08 06:15
30 用enum代替int常量
编写程序的时候更加安全和方便。
vlaueOf(String): 它将常量名字转变成枚举本身。
ordinal(): 返回枚举在数字中的位置。
一个enum用的十分好的例子:
太阳系8个行星中,每颗行星都有其质量和半径,通过这两个属性可以计算出它的表面重力。以下是行星的枚举:
public enum Planet{ MERCURY(3.32e+23, 2.439e6), VENUS (4.869e+24, 6.052e6), ... EARTEH (5.975e+24, 6.378e6); private static final double G = 6.678E-11; private final doiuble mass; private final doiuble radius; rpivate final doiiuble surfaceGravite; Planet(double mass, doiuble radius){ this.mass = mass; this.radius = radius; } public double surfaceWeight(double mass){ //计算方法 } //getter方法}
下面这个程序,可以漂亮的打印出,一个物体在各大行星的重量:
public class WeightTable{ public static void main(String[] args){ double earthWeight = DOuble.parseDouble(arg[0]); double mass = 111; for(Planet p : Planet.values()) System.out.printf("weight on %s is %f%n", p,p.surfaceweight(mass)); }}
特定于常量的方法实现
对于同样的方法,不同的常量有不同的实现。
public 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;}}; abstract double apply(double x, double y);}
不太好的实现,在以后新增常量的时候,可能会忘记添加方法
double apply(double x, double y){ switch(this){ case PLUS: return x+y; ... }}
特定于常量的方法实现有一个不好的地方,就是容器产生许多的样板代码。如何解决这个问题,可以使用策略枚举。
如果多个枚举同时共享相同的行为,考虑策略枚举
以支付加班报酬为例,不同的时间的加班计价方式不同,那么在新建枚举类型的时候,必须选择不同的计价方式:
enum PayrollDay{ MONDAY(PayType.WEEKDAY), TUESDAY(PayType.WEEKDAY) ....; private final PayType payType; PayrollDay(PayType paytype){this.payType = paytype;} double pay(double hourseWorked, double payRate){ return payType.pay(hoursWorked,payRate); } private enum PayType{ WEEKDAY{double overtimePay(double, double){...} }, //其它枚举类型 abstract double overtimePay(double, double); double pay(double, double){ //里面用到了overtimePay } }}
31 用实例域代替序数
每个枚举和一个单独的int值相关联。不要依赖枚举本身的这种依赖的int值,而是应该自己定义一个int值,在构造的时候赋给它。不然,很难维护。
32 用EnumSet代替位域
33 用EnumMap代替序数索引
一个使用的例子:
//Herb是一个类class Herb{ public enum Type {....} private final Type type;}Map<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>());//数组的话,加入的规则是按照Type的类型for(Herb h :garden) herbsByType.get(h.type).add(h);
最好不要使用序数来索引数组,而要使用EnumMap
34 用接口模拟可伸缩的枚举
在30中提到的,特定于常量的方法的实现,可以用接口声明这个抽象方法,枚举拓展这个接口,在特定方法中实现之。至于伸缩性,现在不甚理解。
35 注解优先于命名模式
一般使用命名模式,表示有些程序元素要通过某种工具或者框架进行特殊处理。注意,这个命名模式不是设计模式中的命令模式,而是对元素命名时的一种规则,比如JUnit测试要求用户要用test作为测试方法开头。
命名模式的缺点:
- 文字拼写容易出错。
- 无法确保他们只用于相应的程序元素上。
- 没有提供将参数值和程序元素关联起来的好方法。意即:命名方式不能带参数,对元素处理的时候不方便。即使成功实现,命名或代码也不好看。
举个使用例子:
以测试为例:
旧版JUnit:
void testTargetMethod(){ ...}
新版:
@Testvoid targetMethod(){ ...}
这样子就不用怕拼写出错啦,也可以携带参数。
36 坚持使用Override注解
覆盖方法的时候,使用Override注解,编译器能帮确定是否覆盖了这个方法,而不是编程了重载该方法:
例子:
public class TestClass{ private final char first; ... public boolean equals(TestClass a){ return this.first = a.first; }}
如果没有注解的话,那么,就重载了equals 方法了,因为equals的定义是这个样子的:
public boolean equals(Object o);
运行时,完全没有问题。
更多的帮助:
在Java1.6以上版本,在抽象类或者接口中,标注所有想要覆盖的方法,来覆盖超类或者超接口的方法,无论这些方法是抽象的还是具体的。如,Set 接口没有给Collection接口添加方法,因此他应该在它的所有方法总柏阔Override注解,确保绝对没有给Collection接口添加新的方法。
总结:覆盖方法都打上该标准,具体类实现接口方法除外,因为编译器会出现提醒。
37 用标记接口定义类型
标记接口是没有包含方法声明的接口,只是表明一个类实现了具有某种属性的接口,为此给这个类打上个标记。
这种打标记的方法有两种,一种是标记接口
、另一种是标记注解
(Spring 中@Component
)
标记接口优势:
- 标记接口定义的类型是被标记类的实例实现的;标记注解则没有定义这样的类型。(???)
- 可以却被更精确的锁定。如果注解类型利用
@Target
声明,它可以被应用到任何类或者接口。假设它定义成一个标记接口,就可以用它将唯一的接口拓展成它适用的接口。
标记注解优势:
- 默认的方式添加一个或者多个注解类型元素,给已被使用的注解类型添加更多新型。随着时间推移,简单的标准类型可以演变成更加丰富的注解类型。这种演变对标记接口是不可能的,应为它通常不可能在实现接口之后在给它添加方法。
- 标记注解是注解机制的一部分。因此,标记注解在哪些支持注解的编程元素的框架中同样具有一致性。
如果标记应用到任何程序元素(方法/域),使用注解,接口无法标记方法等。如果编写的方法要接受一个或多个这种标记参数的方法,优先使用标记接口。这样,接口作为相关方法的参数类型,它真正可以为你提供编译时进行类型检查的好处。
- Effective Java:善于使用枚举(enum)和注解(annotation)
- 枚举和注解(Enum and Annotation)
- Annotation & Enum :Java中注解和枚举的使用
- Enum枚举类|注解Annotation
- Effective Java读书笔记(第6章-枚举和注解)
- 【读书笔记】《Effective Java》(5)--枚举和注解
- Effective Java读书笔记二:枚举和注解(30-37)
- Effective Java 读书笔记(五):枚举和注解
- effective java(枚举和注解)
- Effective Java : 枚举和注解
- Java Enum枚举替代方案--Android IntDef/StringDef Annotation注解
- java enum(枚举)的使用和总结
- java enum(枚举)使用详解和总结(转)
- Effective Java——枚举和注解
- [Effective Java]第六章 枚举和注解
- Effective Java读书笔记二:枚举和注解
- Java枚举(Enum)
- Java enum(枚举)的简单使用
- eclipse pydev 配置autopep8
- 声纹识别技术的现状、局限与趋势
- 编程之路小细节-String字符串的部分操作
- 状态码
- Godfather (树形dp + 树的重心)
- Effective Java:善于使用枚举(enum)和注解(annotation)
- border-style: none和border-style:hidden的区别
- js 跨域请求jsonp
- 关于移动端触屏输入控制的API的使用汇总(三)_Unity Android手机触屏事件
- HttpClient -- HTTP工具
- 边缘博客_HTML出错集合及解决方案
- Requests 请求报错 [SSL: SSL_NEGATIVE_LENGTH] dh key too small
- mysql 自定义函数
- 监控,zabbix