本週主題 -- Jakarta Commons Lang

SECTION 01 java.lang.* vs commons-lang.*

目前版本為 2.0 , 可以由此處下載


首先, 讓我們先思考一下, jakarta 為何會有一個 commons-lang 的 opensource 專案呢 ? 在我們使用的 JDK 之中, 都具備著 java.lang.*, 因為預設 import 的原因, 很多人會忽略他的存在, 而 java 歷經了 1.1 ~ 1.4 目前正在制定 1.5 的演進來看, 可以使用的 API 是越來越齊全, 但是是否已經完全足夠了呢 ?!


很可惜, 因為 JDK 的制定需要透過 JCP 組織的認可, 那是一個各大商業軟體公司角力的地方, 而且發布及修改的時程都會非常長久, 因此 commons-lang 就是 jakarta 各個專案常常會使用到的一些功能, 讓他可以加強 java.lang.* 的功能~


SECTION 02 org.apache.commons.lang.*

相對於 java.lang.* , commons-lang 就是建立了一些 Utils 來增加他的功能~ 例如 ArrayUtils, BooleanUtils, CharSetUtils, ClassUtils, NumberUtils, ObjectUtils, StringUtils, SystemUtils 及 WordUtils 等等... 我們拿常用的 StringUtils 來看, 他提供了很多不錯的功能,


例如在 jdk1.3 String 不存在 replaceAll(String regex, String replacement), StringUtils 就提供了 replaceChars(String str, String searchChars, String replaceChars) 來處理全部置換的功能.


NULL 這個空值常常會導致程式的 NullPointerException, 在撰寫接收使用者 request 程式的時候會特別麻煩, 需要多輸入 null 的檢核, 不如使用 EMPTY 空字串來得方便, 所以我們可以將一些 StringUtils.defaultString(request.getParameter("xxx")) 來確保不是 NULL.. 各位可以查詢一下 API, 裡面有許多 methods 都是討論 null 如何處理的方法及原則,


此外, SystemUtils 就是增加了一些 java 系統上面的處理, 例如檢查 java 的版本 isJavaVersionAtLeast , 執行的作業系統等等..


SECTION 03 org.apache.commons.lang.builder

Builder.. 是建立一些特殊功能的次專案, 這也是我認為 commons-lang 非常不錯的次專案.. 最重要的應用就是我們在做專案時, 商業邏輯的 VO 都是標準的 javabean 寫法, 會有一些 getter 與 setter, 可以透過 reflection 來處理 JavaBean 的變化與取值..
  • CompareToBuilder: 加強實作 Comparable.compareTo(Object) methods.

    在 VO 的排序處理中, 我們常常會比較 Object 中的某個數值或字串, 可以利用 Comparable 來處理, 或是利用下面的方法..
     public class MyClass {
    
       String field1;
    
       int field2;
    
       boolean field3;
    
    
    
       ...
    
    
    
       public int compareTo(Object o) {
    
         MyClass myClass = (MyClass) o;
    
         return new CompareToBuilder()
    
           .appendSuper(super.compareTo(o)
    
           .append(this.field1, myClass.field1)
    
           .append(this.field2, myClass.field2)
    
           .append(this.field3, myClass.field3)
    
           .toComparison();
    
       }
    
     }
    
     
    如果, 你需要對整個 Object 做比較呢, 那麼就直接寫簡單的 reflectionCompare, 就可以得到每個欄位的比較結果了 ~
      public int compareTo(Object o) {
    
       return CompareToBuilder.reflectionCompare(this, o);
    
     }
    
     
  • EqualsBuilder: 加強實作 Object.equals(Object) methods.

    EqualsBuilder 和 CompareToBuilder類似, 只是加強實作相等的部分, 如果你對於兩個物件的比較只是限於某些欄位值得比較, 那麼就可以利用以下的方法來確認是否相等..
     public boolean equals(Object o) {
    
       if ( !(o instanceof MyClass) ) {
    
        return false;
    
       }
    
      MyClass rhs = (MyClass) o;
    
      return new EqualsBuilder()
    
                     .appendSuper(super.equals(o))
    
                     .append(field1, rhs.field1)
    
                     .append(field2, rhs.field2)
    
                     .append(field3, rhs.field3)
    
                     .isEquals();
    
      }
    
    
    當然, 你也可以對 Object 內存的所有屬性做比較是否相等..
     public boolean equals(Object o) {
    
       return EqualsBuilder.reflectionEquals(this, o);
    
     }
    
    
  • HashCodeBuilder: 加強實作 Object.hashCode() methods.

    在 Class 之中最好存在一個 hashCode 讓它根據內存數值產生具有唯一性的 hash 判斷值, 不過建立一個 HashCode 產生器可能非常麻煩, 不用煩惱, 使用 commons-lang 將會讓程式更簡單 ~
     public class Person {
    
       String name;
    
       int age;
    
       boolean isSmoker;
    
       ...
    
    
    
       public int hashCode() {
    
         // 你可以寫死 ( hard-coded), 亂數產生, 只要非零並且為奇數的值就可以了.
    
         // 最好是每個 class 都具有不同的 hashcode 數值.
    
         return new HashCodeBuilder(17, 37).
    
           append(name).
    
           append(age).
    
           append(smoker).
    
           toHashCode();
    
       }
    
     }
    
     
    如果所有屬性都要產生, 可以透過 reflection 來處理.
      public int hashCode() {
    
       return HashCodeBuilder.reflectionHashCode(this);
    
     }
    
     
  • ToStringBuilder: 加強實作 Object.toString() methods.

    我們會要求工程師在所有的 VO 都要撰寫 toString() 覆寫 Object.toString(), 因為這樣 debug 的時候才不需要重複地去尋找錯誤的地方,
     public class Person {
    
       String name;
    
       int age;
    
       boolean isSmoker;
    
     
    
       ...
    
     
    
       public String toString() {
    
         return new ToStringBuilder(this).
    
           append("name", name).
    
           append("age", age).
    
           append("smoker", smoker).
    
           toString();
    
       }
    
     }
    
    
    如果所有屬性都要產生, 則直接使用 reflectionToString(this) 也可以, 而且, 如果要去 debug 其他公司所撰寫的程式碼, 也可以透過 ToStringBuilder.reflectionToString(XyzObject); 來了解他物件內數值的狀態~
     public String toString() {
    
       return ToStringBuilder.reflectionToString(this);
    
     }
    
    
  • ReflectionToStringBuilder: 使用 reflection 加強實作 Object.toString() methods .

    ReflectionToStringBuilder 是 extends ToStringBuilder, 而他就是透過 reflection 來完成 toString 的, 他的使用方法很類似 ToStringBuilder.reflectionToString
     public String toString() {
    
       return ReflectionToStringBuilder.toString(this);
    
     }
    
    
    不過, 如果你不希望顯示 password 的欄位, 可以透過 accept 來處理不顯示的數值.
     public String toString() {
    
         return (new ReflectionToStringBuilder(this) {
    
             protected boolean accept(Field f) {
    
                 return super.accept(f) && !f.getName().equals("password");
    
             }
    
         }).toString();
    
     }
    
     



SECTION 04 org.apache.commons.lang.enum

這個 enumeration 是專為原本是 c 語言開發者所建置的 sub-package, 只需要 extends Enum, 就可以簡單地取得 Enum, Map, List 以及 Iterator 等等~
public final class ColorEnum extends Enum {

    public static final ColorEnum RED = new ColorEnum("Red");

    public static final ColorEnum GREEN = new ColorEnum("Green");

    public static final ColorEnum BLUE = new ColorEnum("Blue");



    private ColorEnum(String color) {

        super(color);

    }



    public static ColorEnum getEnum(String color) {

        return (ColorEnum) getEnum(ColorEnum.class, color);

    }



    public static Map getEnumMap() {

        return getEnumMap(ColorEnum.class);

    }



    public static List getEnumList() {

        return getEnumList(ColorEnum.class);

    }



    public static Iterator iterator() {

        return iterator(ColorEnum.class);

    }

}

只需要透過 ColorEnum.getEnum(ColorEnum.RED) 就可以取得 enumeration.


SECTION 05 其他

其他如 exception, math, time 因為我用到的機會不大, exception 的部分大多是增加了一些 Nestable 的 Exception 處理, math 則是 Range 及 計算上的工具, 最後, time 就是一些日期時間的工具, 不過 StopWatch 蠻有趣的, 他是一個計時器, 通常我們在計算執行時間, 可以使用. 大家可以自行參考 API, 如果有需要可以直接使用. SECTION 06 結論

jakarta commons-lang 提供了許多有用的開發工具, 尤其 null 及 Reflection 對於一般工程師是一個麻煩的開發設計, 因此, 如果可以透過 commons-lang 來解決基礎的問題, 我們可以更容易運用 java 在大型的開發之中.
參考 -- 相關書目或相關文章

  1. Jakarta Commons:
    http://jakarta.apache.org/commons/
  2. Jakarta Commons Lang
    http://jakarta.apache.org/commons/lang.html
  3. Jakarta Commons Lang API:
    http://jakarta.apache.org/commons/lang/api/index.html
  4. Oreilly: Using the Jakarta Commons, Part 1:
    http://www.onjava.com/pub/a/onjava/2003/06/25/commons.html?page=2

你可能感兴趣的:(commons)