1. 程式人生 > >Java的值型別和引用型別

Java的值型別和引用型別

一、問題描述

  前幾天因為一個需求出現了Bug。說高階點也挺高階,說白點也很簡單。其實也就是一個很簡單的Java基礎入門時候的值型別和引用型別的區別。只是開發的時候由於自己的問題,導致小問題的出現。還好突然想起來以前看過一篇對於該問題講解的部落格,才能快速定位問題的位置。防止下次再犯,順便也就把這個當做筆記記錄下來,放入自己的Bug集中。

二、值型別和引用型別的比較

  這個大家應該都是沒問題的,很簡單。值型別比較是比較值,引用型別是比較地址。對於正常的操作來說,比較值型別我們可以直接使用 == ,引用型別就使用equals來做比較就不會出現問題。

引用型別 

1     /**
2      * 測試Integer
3      */
4     public static void test_Integer(){
5         Integer number_01 = 10;
6         Integer number_02 = 10;
7         System.out.println(number_01.equals(number_02));
8     }

 

上面的測試結果很明顯是true,絕對沒有問題的。

                                                                  

 

值型別

1     /**
2      * 測試int
3      */
4     public static void test_Int(){
5         int number_01 = 10;
6         int number_02 = 10;
7         System.out.println(number_01 == number_02);
8     }

 

上面的測試結果很明顯是true,絕對沒有問題的。

                                                                    

三、問題

但是問題就出現在,開發的使用為了防止出現為null的時候會被系統使用0來代替,所以就使用了Integer型別來做操作,並且在比較的時候用了 == 。這就很尷尬了,開始自測完全沒出現問題,因為沒到達記錄數。很開心,把程式碼提交下班,妥妥的。但是尷尬的事情來了,測試報告出現在了郵箱裡面了。

初始沒問題的情況

1     /**
2      * 測試Integer
3      */
4     public static void test_Integer(){
5         Integer number_001 = 10;
6         Integer number_002 = 10;
7         System.out.println(number_001 == number_002);
8     }

 

結果:

                                                                     

 

 

 

當記錄超過一定數的時候,出現問題

1     /**
2      * 測試Integer
3      */
4     public static void test_Integer(){
5         Integer number_001 = 128;
6         Integer number_002 = 128;
7         System.out.println(number_001 == number_002);
8     }

 

結果:

                                                                    

四、解決

後面一想,很快確定問題了。是自己的馬虎,偷懶使用了 == ,造成這次問題的出現,當改為equals就可以妥妥的回家了。開始自測沒問題主要還是因為Integer 的快取搞的事情。扒拉到Integer的原始碼,發現裡面用了快取機制,對-128~127的值做了快取,如果在這個值區間內使用==來做比較的話,比較的就是值了,所以才造成開始以為沒問題,後面運行了一段時間後就出現問題了。當不在值區間內就必須使用equals來完成比較。

 1 private static class IntegerCache {
 2         static final int low = -128;
 3         static final int high;
 4         static final Integer cache[];
 5 
 6         static {
 7             // high value may be configured by property
 8             int h = 127;
 9             String integerCacheHighPropValue =
10                 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
11             if (integerCacheHighPropValue != null) {
12                 try {
13                     int i = parseInt(integerCacheHighPropValue);
14                     i = Math.max(i, 127);
15                     // Maximum array size is Integer.MAX_VALUE
16                     h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
17                 } catch( NumberFormatException nfe) {
18                     // If the property cannot be parsed into an int, ignore it.
19                 }
20             }
21             high = h;
22 
23             cache = new Integer[(high - low) + 1];
24             int j = low;
25             for(int k = 0; k < cache.length; k++)
26                 cache[k] = new Integer(j++);
27 
28             // range [-128, 127] must be interned (JLS7 5.1.7)
29             assert IntegerCache.high >= 127;
30         }
31 
32         private IntegerCache() {}
33     }

 

五、總結

當初面試的時候這種東西應該是背的滾瓜爛熟,絕對可以應對面試。但是一旦開發起來就是各種問題都出現了,而且這種東西還不會報出錯日誌,純屬開發問題。歸總來說還是自己的水平不夠,還需要繼續提高。下次要防止這種低階問題的出現,很尷尬。同樣也是對自己學的東西要融匯貫通,而不是每學一個單獨的知識點就夠了,沒有起到聯通的效果。原始碼扒拉一下還是會加深自己的印象。