Java的類型分為兩部分,一個是基本類型(primitive),如int、double等八種基本數據類型;
另一個是引用類型(reference type),如String、List等。而每一個基本類型又各自對應了一個引用類型,稱為包裝類型(或裝箱類型,boxed primitive)。
基本類型與包裝類型的主要區別在於以下三個方面:
1、基本類型只有值,而包裝類型則具有與它們的值不同的同一性(identity)。這個同一性是指,兩個引用是否指向同一個對象,如果指向同一個對象,則說明具有同一性。(與此類似的還有等同性。)
來看一段代碼:
Integer g = new Integer(0);
來看一段代碼:
Integer g = new Integer(0);
Integer h = new Integer(0);
System.out.println(g==h)
以上代碼,兩個對象雖然具有相同的值,但其引用指向的對象卻不相同,因此會輸出false。
再來看一段代碼:
以上代碼,兩個對象雖然具有相同的值,但其引用指向的對象卻不相同,因此會輸出false。
再來看一段代碼:
Integer a = 0;
Integer b = 0;
System.out.println(a==b);
這個會輸出什么呢?別急,再看一段代碼:
這個會輸出什么呢?別急,再看一段代碼:
Integer d = 128;
Integer f = 128;
System.out.println(f==d);
如果你沒有運行這兩段代碼,就知道答案,那么相信你對常量池有一定的了解了。
其實,當我們直接給一個Integer賦予一個int值的時候,它會調用一個valueOf()的方法。所以,如上代碼就相當於:
Integer a = Integer.valueOf(0);
Integer的常量池是由-128至127組成。當我們給一個Integer賦的值在這個范圍之類時就直接會從緩存返回一個相同的引用,所以a==b會輸出true。而超過這個范圍時,就會重新new一個對象。因此,f==d就會輸出一個false。
現在我們再來看一段代碼:
如果你沒有運行這兩段代碼,就知道答案,那么相信你對常量池有一定的了解了。
其實,當我們直接給一個Integer賦予一個int值的時候,它會調用一個valueOf()的方法。所以,如上代碼就相當於:
Integer a = Integer.valueOf(0);
Integer的常量池是由-128至127組成。當我們給一個Integer賦的值在這個范圍之類時就直接會從緩存返回一個相同的引用,所以a==b會輸出true。而超過這個范圍時,就會重新new一個對象。因此,f==d就會輸出一個false。
現在我們再來看一段代碼:
int e = 128;
Integer d = 128;
System.out.println(e==d);
這個會輸出什么呢?答案是true.
因為當在一項操作中混合使用基本類型與包裝類型時,包裝類型會自動拆箱。因此,e和d的比較其實就是int值的比較了。2、基本類型只有功能完備的值,而包裝類型除了其對應的基本類型所有的功能之外,還有一個非功能值:null。
這個會輸出什么呢?答案是true.
因為當在一項操作中混合使用基本類型與包裝類型時,包裝類型會自動拆箱。因此,e和d的比較其實就是int值的比較了。2、基本類型只有功能完備的值,而包裝類型除了其對應的基本類型所有的功能之外,還有一個非功能值:null。
現在來看一段簡單的代碼:
static Integer i;
static Integer i;
public static void main(String[] args) {
if(i == 128){
System.out.println("Unbelieveable~");
}
}
你認為會輸出什么呢?不知道?自己運行一下~~~~
其實這段代碼並不能正確的運行,因為它會報一個NullPointException異常,為什么?因為在定義i的時候,它是Integer類的一個引用,而i沒有初始化,就像所有對象引用一樣,如果沒有初始化那么就賦一個null值。既然現在i是一個null,那么上面已經提到,當混合使用基本類型與包裝類型時,包裝類會自動拆箱。現在i都沒有指向任何對象,因此拆箱的時候就會報一個NullPointException異常。3、基本類型通常比包裝類型更節省時間與空間。
看如下代碼:
你認為會輸出什么呢?不知道?自己運行一下~~~~
其實這段代碼並不能正確的運行,因為它會報一個NullPointException異常,為什么?因為在定義i的時候,它是Integer類的一個引用,而i沒有初始化,就像所有對象引用一樣,如果沒有初始化那么就賦一個null值。既然現在i是一個null,那么上面已經提到,當混合使用基本類型與包裝類型時,包裝類會自動拆箱。現在i都沒有指向任何對象,因此拆箱的時候就會報一個NullPointException異常。3、基本類型通常比包裝類型更節省時間與空間。
看如下代碼:
·Long sum = 0L;
·for(long i = 0;i<Integer.MAX_VALUE;i++)
·{
sum +=i;
}
System.out.println(sum);
毫無疑問,這段代碼能正常運行,但是花費的時間會比較長。因為,在聲明sum變量的時候,一不小心聲明為Long,而不是long。這樣,在這個循環當中就會不斷地裝箱和拆箱,其性能也會明顯的下降。如果把Long改為long,那么經過我的試驗,這段代碼所花費的時間將只有原來的1/5.
經過這三個比較,貌似感覺基本類型已經完勝了包裝類型。但是在如下三個地方,包裝類型的使用會更合理:1、作為集合中的元素、鍵和值。
2、在參數化類型中。比如:你不能這樣寫——ArryList<int>,你只能寫ArrayList<Integer>.
3、在進行反射方法的調用時。
總之,當可以選擇時候,基本類型是要優先於包裝類型。基本類型更加簡單、更加快速。
來源:CSDN
原文:https://blog.csdn.net/cynthia9023/article/details/17413375
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
毫無疑問,這段代碼能正常運行,但是花費的時間會比較長。因為,在聲明sum變量的時候,一不小心聲明為Long,而不是long。這樣,在這個循環當中就會不斷地裝箱和拆箱,其性能也會明顯的下降。如果把Long改為long,那么經過我的試驗,這段代碼所花費的時間將只有原來的1/5.
經過這三個比較,貌似感覺基本類型已經完勝了包裝類型。但是在如下三個地方,包裝類型的使用會更合理:1、作為集合中的元素、鍵和值。
2、在參數化類型中。比如:你不能這樣寫——ArryList<int>,你只能寫ArrayList<Integer>.
3、在進行反射方法的調用時。
總之,當可以選擇時候,基本類型是要優先於包裝類型。基本類型更加簡單、更加快速。
來源:CSDN
原文:https://blog.csdn.net/cynthia9023/article/details/17413375
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!