Effective Java:善于使用枚举(enum)和注解(annotation)
2017-11-26 14:28
597 查看
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(){ ... }
新版:
@Test void targetMethod(){ ... }
这样子就不用怕拼写出错啦,也可以携带参数。
36 坚持使用Override注解
覆盖方法的时候,使用Override注解,编译器能帮确定是否覆盖了这个方法,而不是编程了重载该方法:例子:
public class TestClass{ private final char first; ... public af3e 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声明,它可以被应用到任何类或者接口。假设它定义成一个标记接口,就可以用它将唯一的接口拓展成它适用的接口。
标记注解优势:
默认的方式添加一个或者多个注解类型元素,给已被使用的注解类型添加更多新型。随着时间推移,简单的标准类型可以演变成更加丰富的注解类型。这种演变对标记接口是不可能的,应为它通常不可能在实现接口之后在给它添加方法。
标记注解是注解机制的一部分。因此,标记注解在哪些支持注解的编程元素的框架中同样具有一致性。
如果标记应用到任何程序元素(方法/域),使用注解,接口无法标记方法等。如果编写的方法要接受一个或多个这种标记参数的方法,优先使用标记接口。这样,接口作为相关方法的参数类型,它真正可以为你提供编译时进行类型检查的好处。
相关文章推荐
- Annotation & Enum :Java中注解和枚举的使用
- Java Enum枚举替代方案--Android IntDef/StringDef Annotation注解
- 高阶Java枚举类型enum使用详解
- JUnit 4 使用 Java 5 中的注解(annotation)
- java enum枚举的使用
- java中Enum(枚举)的使用
- JUnit 4 使用 Java 5 中的注解(annotation)
- JUnit 4 使用 Java 5 中的注解(annotation) 【转】
- Java基础笔记 – Annotation注解的介绍和使用 自定义注解
- java enum(枚举)使用详解 + 总结
- Java基础-学习使用Annotation注解对象
- 高阶Java枚举类型enum使用详解
- Java基础笔记 – Annotation注解的介绍和使用 自定义注解
- Java基础-学习使用Annotation注解对象
- Java自定义注解Annotation的使用
- Java —— 枚举(Enum)的使用
- 高阶Java枚举类型enum使用详解
- Java Annotation 注解的介绍和使用 自定义注解
- 高阶Java枚举类型enum使用详解