風人園

          弱水三千,只取一瓢,便能解渴;佛法無邊,奉行一法,便能得益。
          隨筆 - 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 風人園 閱讀(559) 評論(0)  編輯  收藏 所屬分類: Java

          主站蜘蛛池模板: 巴里| 梧州市| 平谷区| 镇巴县| 防城港市| 新兴县| 深泽县| 佛坪县| 大化| 阿拉善盟| 陆丰市| 白银市| 昌图县| 南昌市| 原阳县| 金门县| 信丰县| 大同市| 吴忠市| 紫金县| 乌拉特后旗| 双鸭山市| 沙河市| 华宁县| 缙云县| 金平| 彝良县| 凌海市| 叙永县| 武安市| 临泉县| 苗栗县| 敦化市| 页游| 民县| 思茅市| 邯郸市| 芜湖市| 南昌市| 嵊州市| 泰顺县|