风人园

弱水三千,只取一瓢,便能解渴;佛法无边,奉行一法,便能得益。
随笔 - 99, 文章 - 181, 评论 - 56, 引用 - 0
数据加载中……

jdk1.5 Type Safe Enum

Type Safe Enum

Tiger的改进其实真的称得上是顺应民意,里面的好多特性都可以在两本Java巨著<<Think In Java>;>;和<<Effective Java>;>;发现一些端倪.
(不得不承认,<<Think In Java>;>;和<<Effective Java>;>;是Java历史上最经典的两本书,多读多受益)
比如,之前提到过的Genric,在<<Think In Java>;>; 第九章介绍Colletion时就对Genric作出了预期,同时也实现某种形式的Genric(TIJ 2ND,P449-P455).
另外,Think In Java里也提及了利用interface来定义一组常量的方法(P358-P360),不少标准的Java库类也使用了这种方法(如java.util.zip.ZipConsts.不过,你将会发现,在Tiger里它已经不复存在了)
这种做法叫做Const Interface,大家也许或多或少都使用过.但是,Const Interface的方式在<<Effective Java>;>;受到了极大的否定(Item 17).书里提出了使用Type Safe Enum的方法(Item 21)来取代Const Interface.让我们对比一下以下两段代码

Const Interface
[code]
//SeasonConst.java
// Constant interface pattern - do not use!
public interface SeasonConst {
public static final int SPRING = 1;
public static final int SUMMER = 2;
public static final int AUTUMN = 3;
public static final int WINTER = 4;
}

//TestConst.java
//using of Constant interface
public class TestConst implements SeasonConst{
public void seasonLiving(int season){
if(season==SPRING){
System.out.println("we BBQ at SPRING");
}
else if(season==SUMMER){
System.out.println("we swim at SUMMER");
}
else if(season==AUTUMN){
System.out.println("we kite at AUTUMN");
}
else if(season==WINTER){
System.out.println("we skate at WINTER");
}
else{
System.out.println("What ?");

}
}
public static void main(String args[]){
TestConst t = new TestConst();
t.seasonLiving(SPRING);
t.seasonLiving(WINTER);
t.seasonLiving(WINTER+1);
//t.sersonLiving(WEEK_DAY.MONDAY);//程序无法和其他常数完整的区分
}
}
[/code]

Type Safe Enum
[code]
//SeasonEnum.java
// The typesafe enum (j2sdk1.4)pattern
public class SeasonEnum {
private final String name;
private SeasonEnum(String name) {
this.name = name;
}
public String toString() { return name; }
public static final SeasonEnum SPRING = new SeasonEnum("SPRING");
public static final SeasonEnum SUMMER = new SeasonEnum("SUMMER");
public static final SeasonEnum AUTUMN = new SeasonEnum("AUTUMN");
public static final SeasonEnum WINTER = new SeasonEnum("WINTER");
}

//TestEnum.java
//using of typesafe enum (j2sdk1.4)
public class TestEnum{
public void seasonLiving(SeasonEnum season){
if(season==SeasonEnum.SPRING){
System.out.println("we BBQ at "+season);
}
else if(season==SeasonEnum.SUMMER){
System.out.println("we swim at "+season);
}
else if(season==SeasonEnum.AUTUMN){
System.out.println("we kite at "+season);
}
else if(season==SeasonEnum.WINTER){
System.out.println("we skate at "+season);
}
else{
System.out.println("What ?");
}
}
public static void main(String args[]){
TestEnum t = new TestEnum();
t.seasonLiving(SeasonEnum.SPRING);
t.seasonLiving(SeasonEnum.WINTER);
//t.seasonLiving(WINTER+1);no way to put a season not in the SeasonEnum

}
}
[/code]

可以看出,Type Safe Enum在以下几个方面优于Const Interface
1.不会违背OO继承的意义.
2.类型安全,不会有无意义的常数混进正常常数中
3.保持自己的独立性,不像Const interface再编译后就失去了意义
4.可直接用于print
5.作为一个Object,可以拥有自己的方法,变量,可以继承,implement interface

但是,相对的,Type Safe Enum在使用中也有几点不利的地方

1.不能直接用于switch
2.必须跟上类名,增加复杂性
3.繁琐

于是,Tiger中引入了 typesafe Enum和static import ,同时启用了一个新的关键字enum(这也是Tiger中引入的唯一一个关键字).再配合上Genric,使得整个结构变得严谨而易用.

让我们还是使用方才的例子来说明吧,先来一个最简单的例子.
[code]
public class TestEnumTiger1{
public enum SeasonSimpliest {        SPRING,        SUMMER,        AUTUMN,        WINTER}


public void seasonLiving(SeasonSimpliest season){

if(season==SeasonSimpliest.SPRING){
System.out.println("we BBQ at "+season);
}
else if(season==SeasonSimpliest.SUMMER){
System.out.println("we swim at "+season);
}
else if(season==SeasonSimpliest.AUTUMN){
System.out.println("we kite at "+season);
}
else if(season==SeasonSimpliest.WINTER){
System.out.println("we skate at "+season);
}
else{
System.out.println("What ?");
}
}
public static void main(String args[]){
TestEnumTiger1 t = new TestEnumTiger1();
t.seasonLiving(SeasonSimpliest.SPRING);
t.seasonLiving(SeasonSimpliest.WINTER);
System.out.println("the seasong is :"+SeasonSimpliest.SPRING);
//t.seasonLiving(WINTER+1);no way to put a season not in the SeasonEnum
//t.seasonLiving(new SeasonSimpliest("Five Season"));no way to put a season not in the SeasonEnum

}
}[/code]

这里面的常量直接用enum修饰,再加上一个名字和所需常量就可以了.
enum SeasonSimpliest {        SPRING,        SUMMER,        AUTUMN,        WINTER}
不过,不要被这种形式所迷惑,以为enum是一个primtive type,与int,boolean一样,那就错了.
让我们编译一下这个文件,再看看编译后的目录
里面除了有TestEnumTiger1.java,TestEnumTiger1.class之外,还有一个TestEnumTiger1$SeasonSimpliest.class,这就暴露了enum的某些行为方式,它在某种意义上是一个class.
在上面的源码中,它成了一个inner-class.

OK.让我们改改代码,把enum作为一个独立个体来处理
[code]
//SeasonSimpliest.java
package test;
public enum SeasonSimpliest {SPRING,SUMMER,AUTUMN,WINTER}
[/code]

[code]
//enum & static import
package test;
import static test.SeasonSimpliest.*;

public class TestEnumTiger2{

public void seasonLiving(SeasonSimpliest season){
switch(season){
case SPRING:
System.out.println("we BBQ at "+season);
break;
case SUMMER:
System.out.println("we swim at "+season);
break;
case AUTUMN:
System.out.println("we kite at "+season);
break;
case WINTER:
System.out.println("we skate at "+season);
break;
default:throw new AssertionError("something must be wrong,no such a season");
}
}
public static void main(String args[]){
TestEnumTiger2 t = new TestEnumTiger2();
t.seasonLiving(SPRING);
t.seasonLiving(WINTER);
System.out.println("the season is :"+SUMMER);
//t.seasonLiving(WINTER+1);no way to put a season not in the SeasonEnum
//t.seasonLiving(new SeasonSimpliest("Five Season"));no way to put a season not in the SeasonEnum

}
}

[/code]

为了使整个代码显得更加简洁,我引入import static ,稍后再作更详细介绍,现在先来看看enum的好处.
1.避免了使用Const interface
2.很简单的定义方式
3.Type Safe,类型安全的,不会和其他的常量混绕.
4.可以使用switch
5.作为一个Class,它可以有自己Method,Field,也可以implements interface.

为了更好的说明第5点,我给大家展示一个复杂的enum type.

[code]
//SeasonComplex.java
//implements interface,owner method & field
public  enum SeasonComplex implements Comparable<SeasonComplex>; {
        SPRING(1),
        SUMMER(2),
        AUTUMN(3),
        WINTER(4);
private final int seasonNumber;
Season(int value){
        seasonNumber=value;
        }
public int seasonNumber(){
        return seasonNumber;
}
public int compare(Season c){
return seasonNumber - c.seasonNumber;
}
public String description(){
return this+":第"+ seasonNumber +"季";
}
};

[/code]

具体的我就不一一写清楚,大家好好体会吧.

posted on 2006-12-16 15:50 风人园 阅读(549) 评论(0)  编辑  收藏 所属分类: Java