- 论坛徽章:
- 0
|
老虎来了,你准备好了吗?(增加for-each)
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
- //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);//程序无法和其他常数完整的区分
- }
- }
复制代码
Type Safe Enum
- //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
- }
- }
复制代码
可以看出,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,使得整个结构变得严谨而易用.
让我们还是使用方才的例子来说明吧,先来一个最简单的例子.
- 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
- }
- }
复制代码
这里面的常量直接用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作为一个独立个体来处理
- //SeasonSimpliest.java
- package test;
- public enum SeasonSimpliest {SPRING,SUMMER,AUTUMN,WINTER}
复制代码
- //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
- }
- }
复制代码
为了使整个代码显得更加简洁,我引入import static ,稍后再作更详细介绍,现在先来看看enum的好处.
1.避免了使用Const interface
2.很简单的定义方式
3.Type Safe,类型安全的,不会和其他的常量混绕.
4.可以使用switch
5.作为一个Class,它可以有自己Method,Field,也可以implements interface.
为了更好的说明第5点,我给大家展示一个复杂的enum type.
- //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 +"季";
- }
- };
复制代码
具体的我就不一一写清楚,大家好好体会吧.
时间不早,关于static import 明天再慢慢说. |
|