您的位置:首页 > 其它

第6章 枚举和注解

2013-08-07 13:58 169 查看

30、用enum代替int常量

枚举类型是指由一组固定的常量组成合法值的类型。int枚举模式如public static final int APP = 0;int枚举是编译时常量,被编译到使用它们的客户端中,如果其发生变化,客户端必须重新编译否则导致行为的不确定性。

java枚举类型基本思想:它们就是通过公有的静态final域为每个枚举常量导出实例的类。它提供了编译时的类型安全。它还允许添加任意的方法和域,并实现任意的接口,提供了所有Object方法的高级实现,实现了Comparable和Serializable接口,并针对枚举类型的可任意改变性设计了序列化方式。枚举类可以通过元素及其构造包含很多实例,然后通过这些实例调用不同状态的方法(有点像策略模式哎···)。如:

publicenum Planet{

EARTH (5.975e+24,6.378e6),//声明了枚举的元素及构造了它们

MARS(6.419e+23,3.393e6),//注意是“,”结尾

Planet(double mass,double radius){···}//对应的构造方法

}

调用如:Planet.EARTH.方法();

Planet.values();按照声明顺序返回它的值数组。可以这么用:for(Planet p : Planet.value()){}

一种方法可以将不同的行为与每个枚举常量关联起来(用switch方法代码脆弱,需要写“抛出异常”的语句):在枚举类型中声明一个抽象的方法,并在常量类主体中用具体的方法覆盖每个常量的抽象。如:

publicenum Operation{

PLUS(“+”){double apply(double x,doubley){return x+y;}},//特定于常量的方法实现。可以再定义一个由+转成PLUS的方法,用Map实现就可以。

MINUS(“-”){double apply(double x,doubley){return x-y;}};//最后一个枚举元素后面跟“;”号

abstract double apply(double x,double y);

private final String symbol;

Operation(String symbol){this.symbol
= symbol;}

@override public String toString(){returnsymbol;}//重写toString

}

私有嵌套枚举可以用于策略枚举,实现不同的方法操作。如将平常日和休息日加班工资的计算方法作为两类日期的特定于常量方法实现,在外部类中通过内部类枚举元素就可以调用内部类不同元素对应的方法了。(跟策略模式如出一辙)(p135)

31、用实例域代替序数

永远不要根据枚举的序数导出与它关联的值,而是要将它保存在一个实例域中。即通过构造方法指定枚举的值,如:

publicenum Ensemble{

SOLO(1),DUET(2);//保存值

privatefinal int numberOfMusicians;

Ensemble(intsize){this. numberOfMusicians = size;}

public intnumberOfMusicians(){return numberOfMusicians ;}

}

32、用EnumSet代替位域

枚举类型要用在集合中,没有理由用位域(按bit位存储)来表示它。

33、用EnumMap代替序数索引

以枚举类型作为key键,有一种非常快速的M安排、实现专门用枚举键,为EnumMap。

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

枚举类型不是可扩展的,但接口类型是可扩展的。

public enum BasicOperation implementsOperation{},调用,传入的参数可以这么写test(Arrays.asList(BasicOperation.values()),x,y);,test原型是test(Collection<?extends Operation> opSet,double x,double y){for(Operation op : opSet){}}

35、注解优先于命名模式

命名模式(naming pattern)缺点:(1)文字拼写错误会导致失败,且没有任何提示;(2)无法确保他们只用于相应的程序元素上;(3)它们没有提供将参数值与程序元素关联起来的好方法。

元注解,定义注解类型如:

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public@interface Test{}

@Retention(RetentionPolicy.RUNTIME)元注解表明,所对应方法的注解应该在运行时保留,如果没有保留,测试工具就无法知道Test注解。@Target(ElementType.METHOD)元注解表明,对应方法的注解只在方法声明中才是合法的:它不能运用到类声明、域声明或者其他程序元素上。

之后在每个要测试的方法前(public前面),添加@Test即可。在实际测试例子中,用类名.getDeclaredMethods()获得Method数组。通过增强for循环,循环里面if(方法.isAnnotationPresent(Test.class)){则进行方法测试即可},并通过调用Method.invoke反射式地运行类中所有标注了Test的方法。

针对只在抛出特殊异常时才成功的测试添加支持。只需在Test里内容改成Class<? extends Exception> value();,测试时,直接提取Method.getAnnotation(类名.class).value();

36、坚持使用Override注解

应该在你想要覆盖超类声明的每个方法声明中使用Override注解。

37、用标记接口定义类型

标记接口(marker interface)是没有包含方法声明的接口,而只是指明一个类实现了具有某种属性的接口(例如Serializable)。

标记类型有两点胜过标记注解:(1)标记接口定义的类型是由被标记类的实例实现的;标记注解则没有定义这样的类型。这类型能够在编译时发现错误而标记注解只能在运行时发现错误(文中举例还是有点纳闷)。(2)标记接口可以被更加精确地进行锁定。

标记注解优势:(1)它可以通过默认的方式添加一个或多个注解类型元素,给已被使用的注解类型添加更多的信息。(2)标记注解是更大的注解机制的一部分。

选择:如果标记是应用到任何程序元素而不是类或者接口,就必须使用注解,因为只有类和接口可以用来实现或者扩展接口。如果想要定义一个任何新方法都不会与之关联的类型,标记接口就是最好的选择。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: