asklxf

          A java developer's notebook.

          常用鏈接

          統(tǒng)計

          積分與排名

          最新評論

          JDK源碼分析:java.lang.Boolean

          閑來無事,開始研究JDK源碼(jdk 1.5 b2),先找了一個最簡單的java.lang.Boolean開始解剖。

          由于水平有限,難免有不少錯誤,還請大家指正!

          首先我們剔除所有的方法和靜態(tài)變量,Boolean的核心代碼如下:

          public final class Boolean implements java.io.Serializable,Comparable
          {
              private final boolean value;
          }

          很明顯,凡是成員變量都是final類型的,一定是immutable class,這個Boolean和String一樣,一旦構造函數執(zhí)行完畢,實例的狀態(tài)就不能再改變了。

          Boolean的構造函數有兩個:

          public Boolean(boolean value) {
              this.value = value;
          }
          public Boolean(String s) {
              this(toBoolean(s));
          }

          都很簡單就不多說了。

          另外注意到Boolean類實際上只有兩種不同狀態(tài)的實例:一個包裝true,一個包裝false,Boolean又是immutable class,所以在內存中相同狀態(tài)的Boolean實例完全可以共享,不必用new創(chuàng)建很多實例。因此Boolean class還提供兩個靜態(tài)變量:

          public static final Boolean TRUE = new Boolean(true);
          public static final Boolean FALSE = new Boolean(false);

          這兩個變量在Class Loader裝載時就被實例化,并且申明為final,不能再指向其他實例。

          提供這兩個靜態(tài)變量是為了讓開發(fā)者直接使用這兩個變量而不是每次都new一個Boolean,這樣既節(jié)省內存又避免了創(chuàng)建一個新實例的時間開銷。

          因此,用
              Boolean b = Boolean.TRUE;

              Boolean b = new Boolean(true);
          要好得多。

          如果遇到下面的情況:
              Boolean b = new Boolean(var);
          一定要根據一個boolean變量來創(chuàng)建Boolean實例怎么辦?

          推薦你使用Boolean提供的靜態(tài)工廠方法:
              Boolean b = Boolean.valueOf(var);
          這樣就可以避免創(chuàng)建新的實例,不信看看valueOf()靜態(tài)方法:

          public static Boolean valueOf(boolean b) {
              return (b ? TRUE : FALSE);
          }

          這個靜態(tài)工廠方法返回的仍然是兩個靜態(tài)變量TRUE和FALSE之一,而不是new一個Boolean出來。雖然Boolean非常簡單,占用的內存也很少,但是一個復雜的類用new創(chuàng)建實例的開銷可能非常大,而且,使用工廠方法可以方便的實現緩存實例,這對客戶端是透明的。所以,能用工廠方法就不要用new。

          和Boolean只有兩種狀態(tài)不同,Integer也是immutable class,但是狀態(tài)上億種,不可能用靜態(tài)實例緩存所有狀態(tài)。不過,SUN的工程師還是作了一點優(yōu)化,Integer類緩存了-128到127這256個狀態(tài)的Integer,如果使用Integer.valueOf(int i),傳入的int范圍正好在此內,就返回靜態(tài)實例。

          hashCode()方法很奇怪,兩種Boolean的hash code分別是1231和1237。估計寫B(tài)oolean.java的人對這兩個數字有特別偏好:

          public int hashCode() {
              return value ? 1231 : 1237;
          }

          equals()方法也很簡單,只有Boolean類型的Object并且value相等才返true:

          public boolean equals(Object obj) {
              if (obj instanceof Boolean) {
                  return value == ((Boolean)obj).booleanValue();
              }
              return false;
          }

          順便提一句:很多人寫equals()總是在第一行寫:
             if (obj==null) return false;
          其實完全沒有必要,因為如果obj==null,下一行的
              if (obj instanceof Type)
          就肯定返回false,因為(null instanceof AnyType) = false。
          詳細內容請參考《Effective Java》第7條:Obey the general contract when overriding equals。

          其他的方法如toString()就更簡單了,只要稍微熟悉java的程序員相信都能寫出來,我就不多說了。

          總結

          1.如果一個類只有有限的幾種狀態(tài),考慮用幾個final的靜態(tài)變量來表示不同狀態(tài)的實例。
          例如編寫一個Weekday類,狀態(tài)只有7個,就不要讓用戶寫new Weekday(1),直接提供Weekday.MONDAY即可。

          2.要防止用戶使用new生成實例,就取消public構造函數,用戶要獲得靜態(tài)實例的引用有兩個方法:如果申明public static var就可以直接訪問,比如Boolean.TRUE,
          第二個方法是通過靜態(tài)工廠方法:Boolean.valueOf(?)

          3.如果不提供public構造函數,讓用戶只能通過上面的方法獲得靜態(tài)變量的引用,還可以大大簡化equals()方法:
              public boolean equals(Object obj) {
                  return this==obj;
              }
          可以直接用==比較引用,絕對沒有問題,而且效率最高。

          4.為什么JDK的Boolean沒有實現上面第3點?因為那兩個static變量TRUE和FALSE是在jdk 1.2以后才有的,由于前面的版本已經把構造函數申明為public,所以為了保持客戶端代碼能夠不修改也在后面的版本中運行,只好繼續(xù)提供public構造函數。

          posted on 2005-12-02 10:35 Xuefeng's Weblog 閱讀(391) 評論(0)  編輯  收藏 所屬分類: Java Basic


          只有注冊用戶登錄后才能發(fā)表評論。


          網站導航:
           
          主站蜘蛛池模板: 黑河市| 花垣县| 镇赉县| 姚安县| 二连浩特市| 鸡泽县| 宾阳县| 桦川县| 仁怀市| 唐山市| 岳阳县| 西华县| 大冶市| 越西县| 兴山县| 徐闻县| 简阳市| 咸宁市| 拜泉县| 子长县| 浠水县| 安庆市| 新乐市| 绵竹市| 神农架林区| 额济纳旗| 会宁县| 黎川县| 宁夏| 万宁市| 翁牛特旗| 天柱县| 和田县| 广德县| 玉林市| 岑溪市| 开阳县| 卓尼县| 安西县| 和政县| 五大连池市|