todayx.org
          todayx.org
          posts - 39,comments - 60,trackbacks - 0
          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/

          等于還是不等于?

          看來看下面的一段代碼:

           

             代碼片段1

          Java代碼  收藏代碼
          1. public static void main(final String[] args) {  
          2.     Integer a = new Integer(100);  
          3.     Integer b = 100;  
          4.     System.out.println(a == b);   
          5. }  

           

           這段代碼的輸出是什么?相信很多人都會很容易的猜到:false,因為a、b兩個對象的地址不同,用“==”比較時是false。恭喜你,答對了。

           

          再看下面的一段代碼:

            

             代碼片段2

          Java代碼  收藏代碼
          1. public static void main(final String[] args) {  
          2.     Integer a = 100;  
          3.     Integer b = 100;  
          4.     System.out.println(a == b);   
          5. }  

           

          你可能會回答,這沒什么不一樣啊,所以還是false。很遺憾,如果你執行上面的一段代碼,結果是true。

           

          上面的代碼可能讓你有些意外,那好吧,再看看下面的這段代碼:

           

              代碼片段3

          Java代碼  收藏代碼
          1. public static void main(final String[] args) {  
          2.     Integer a = 156;  
          3.     Integer b = 156;  
          4.     System.out.println(a == b);   
          5. }  

           結果是true嗎?很遺憾,如果你執行上面的一段代碼,結果是false。

           

           感到吃驚嗎?那最后再看下面的一段代碼:

           

              代碼片段4

          Java代碼  收藏代碼
          1. public static void main(final String[] args) {  
          2.     Integer a = Integer.valueOf(100);  
          3.     Integer b = 100;  
          4.     System.out.println(a == b);   
          5. }  

          最后的結果,可能你已經猜到了,是true。

          為什么會這樣?

          現在我們分析一下上面的代碼??梢院苋菀椎目闯?,這一系列代碼的最終目的都是用“==”對兩個對象進行比較。Java中,如果用“==”比較兩個對象結果為true,說明這兩個對象實際上是同一個對象,false說明是兩個對象。

           

          現在,我們來看看為什么會出現上面的現象。

           

          我們先看代碼片段4:最后的運行結果是true,說明a、b兩個對象實際上是同一個對象。但是a對象是通過調用Integer的valueOf方法創建的,而b對象是通過自動裝箱創建出來的,怎么會是同一個對象呢?難道問題在字節碼那里,畢竟Java程序是依靠虛擬器運行字節碼來實現的。

           

          通過jdk中自帶的工具javap,解析字節碼,核心的部分摘取如下:

          Java代碼  收藏代碼
          1. 0:  bipush  100  
          2. 2:  invokestatic    #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;  
          3. 5:  astore_1  
          4. 6:  bipush  100  
          5. 8:  invokestatic    #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;  

          代碼中我們只調用了一次Integer.valueOf方法,但是字節碼中出現了兩次對Integer.valueOf方法的調用。那么另一次是哪里呢?只可能在自動裝箱時調用的。因此這段代碼實際上等價于:

          Java代碼  收藏代碼
          1. public static void main(final String[] args) {  
          2.     Integer a = Integer.valueOf(100);  
          3.     Integer b = Integer.valueOf(100);  
          4.     System.out.println(a == b);   
          5. }  

           現在問題就簡單了:看jdk源代碼,查看valueOf方法的具體實現:

          Java代碼  收藏代碼
          1. public static Integer valueOf(int i) {  
          2.     final int offset = 128;  
          3.     if (i >= -128 && i <= 127) { // must cache   
          4.         return IntegerCache.cache[i + offset];  
          5.     }  
          6.     return new Integer(i);  
          7. }  

           

          看到這兒,上面的代碼就很明確了:對于-128到127的數字,valueOf返回的是緩存中的對象。所以兩次調用Integer.valueOf(100)返回的都是同一個對象。

          我們再先看代碼片段3:根據上面的分析,代碼片段3實際上等價于以下代碼:

          Java代碼  收藏代碼
          1. public static void main(final String[] args) {  
          2.     Integer a = Integer.valueOf(156);  
          3.     Integer b = Integer.valueOf(156);  
          4.     System.out.println(a == b);   
          5. }  

           由于156不在-128到127范圍內,所以兩個對象都是通過new Integer()的方式創建的,所以最后結果為false。

           

           片段1和片段2就不做具體分析了,相信讀者可以自行分析。

           

           最后,請大家思考一下問題:通過上面的分析,了解到整數的自動裝箱是通過Integer.valueOf(int number)實現的,那么自動拆箱是如何實現的呢?


          歷史上的今天
          回顧歷史的今天,歷史就像生活的一面鏡子;可以了解歷史的這一天發生的事件;借古可以鑒今;歷史是不能忘記的.要記住歷史的每一天
          http://www.todayx.org/
          posted on 2012-02-01 00:21 todayx.org 閱讀(1976) 評論(3)  編輯  收藏

          FeedBack:
          # re: Java迷題:等于,還是不等于?
          2012-02-01 13:57 | 楊Coder
          呵呵!不分析底層,還真不知道有這么一回事!作者很有探究精神。  回復  更多評論
            
          # re: Java迷題:等于,還是不等于?
          2012-02-05 14:21 | allenny
          1,2,4很好理解,3倒是第一次注意到,Integer只有8位嗎?  回復  更多評論
            
          # re: Java迷題:等于,還是不等于?
          2012-03-30 18:29 | 網友
          看起來眼熟呢?
          http://xiaoyu1985ban.iteye.com/blog/1384191
          有點不地道哦。  回復  更多評論
            

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


          網站導航:
           
          主站蜘蛛池模板: 乐亭县| 井冈山市| 西藏| 九龙坡区| 利川市| 信阳市| 银川市| 苏尼特右旗| 微博| 扎鲁特旗| 肥东县| 平和县| 商水县| 辉县市| 崇义县| 枣庄市| 万宁市| 衡南县| 喀喇沁旗| 连山| 洪湖市| 溧水县| 尼玛县| 福建省| 科尔| 临海市| 徐水县| 临桂县| 固阳县| 汝阳县| 屯留县| 贵定县| 定兴县| 五大连池市| 苗栗市| 鸡泽县| 右玉县| 灵武市| 肃北| 五家渠市| 曲麻莱县|