一、Java資料型別
1、在說裝箱與拆箱之前,先說一下Java的基本資料型別,Java從資料型別上可以劃分為值型別與參考型別,值型別是四類八種,分別是:
- 整數型:byte?,short?,int?,long
- 浮點型:?oat,double
- 字符型:char
- 布爾型:boolean
| 資料型別 | 記憶體 | 默認值 | 包裝類 |
|---|---|---|---|
| byte | 8位 | 0 | Byte |
| short | 16位 | 0 | short |
| int | 32位 | 0 | Integer |
| long | 64位 | 0L或0l | Long |
| float | 32位 | 0.0F或0.0f | Float |
| double | 64位 | 0.0D或0.0d | Double |
| char | 16位 | \u0000 | Character |
| boolean | 8位 | flase | Boolean |
2、參考型別:
- 陣列
- 類(class)
- 介面(Interface)
- 列舉(enum)
3、值型別與參考型別的區別
- 從概念方面上來說:
- 值型別:變數名指向具體的值
- 參考型別:變數名指向資料物件的記憶體地址
- 從記憶體構建方面上來說:
- 值型別:變數在宣告之后,Java就會立刻分配給它記憶體空間
- 參考型別:它以特殊的方式(類似C指標)指向物件物體,這類變數宣告時不會分配記憶體,只是存盤
- 從使用方面上來說:
- 值型別:使用時需要賦具體值,判斷時用 ” == “號
- 參考型別:使用時可以賦null,判斷時使用 equals 方法
二、Java資料型別轉換
1、自動轉換
-
定義:程式在執行程序中“悄然”進行的轉換,不需要用戶提前宣告,一般是從位數低的型別向位數高的型別轉換
-
優先關系:按從低到高的順序轉換,不同型別資料間的優先
關系如下:
- 低--------------------------------------------->高
- byte,short,char-> int -> long -> float -> double
-
轉換規則:
運算中,不同型別的資料先轉化為同一型別,然后進行運算
運算元1型別 運算元2型別 轉換后的型別 byte、short、char int int byte、short、char、int long long byte、short、char、int、long float float byte、short、char、int、long、float double double
2、強制轉換
-
定義:強制型別轉換則必須在代碼中宣告,轉換順序不受限制
-
格式:在需要轉型的資料前加上“( )”,然后在括號內加入需要轉化的資料型別
-
結果:精度可能會丟失,也可能更加精確
int x; double y; x = (int)3.14 + (int)5.20 //精度丟失 y = (double)x + (double)8 //精度提升 輸出:x = 8;y = 16.0
三、Java之裝箱與拆箱
1、包裝類
- Java是面向物件語言,號稱萬事萬物皆物件,因此,8種基本資料型別有了對應的類,這就是包裝類
2、什么是裝箱與拆箱
-
裝箱:將值型別裝換成參考型別的程序
-
拆箱:將參考型別轉換成值型別的程序
-
自動裝箱:
int x = 3; Integer y = x; //int --> Integer,Integer y = x <==> Integer y = Integer.valueOf(x) -
自動拆箱:
Integer x = new Integer(5); int y = x; //Integer --> int,int y = x <==> int y = x.intValue()
3、裝箱和拆箱是如何實作的
- 裝箱程序是通過呼叫包裝器的valueOf方法實作的
- 拆箱程序是通過呼叫包裝器的 xxxValue方法實作的,(xxx代表對應的基本資料型別)
4、注意點:
-
大量使用自動拆裝箱會使性能降低,還會造成大量的記憶體消耗
-
在多載方法中,可能出現問題
List<Integer> list = new ArrayList<>(); Integer x,y,z; x = 1;y = 2;z = 4; list.add(x);list.add(y);list.add(z); list.remove(2);
在上面這段代碼中ArrayList.remove方法有兩個多載方法,那么list.remove(2)是呼叫了哪個方法,remove掉的是值為2的物件,還是remove了index為2,值為4的那個物件呢?
在這種情況下,編譯器不會進行自動拆裝箱,所以呼叫的是remove(int index),index為2值為4的這個Integer物件會被remove.
如果要呼叫 remove(Object o)的方法,應該這么寫 list.remove(y)
-
快取值問題
-
案例決議:
Integer i1 = 100; Integer i2 = 100; Integer i3 = 200; Integer i4 = 200; System.out.println(i1==i2); System.out.println(i3==i4); Output: true false -
觀察原始碼:
Intteger.valueOf方法
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }IntegerCache類
private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = https://www.cnblogs.com/kalton/p/sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; } private IntegerCache() {} }從原始碼可以看出,在通過valueOf方法創建Integer物件的時候,如果數值在[-128,127]之間,便回傳指向IntegerCache.cache中已經存在的物件的參考;否則創建一個新的Integer物件
-
Byte、Short、Integer、Long四種包裝類默認創建了數值為[-128,127]的相應型別的快取資料,但是超出此范圍仍會創建新的物件,
-
Character默認會創建[0,127]的回應型別的快取資料
-
兩種浮點型沒有實作常量池技術,在某個范圍內的整型數值的個數是有限的,而浮點數卻不是
包裝類 常量池 常量池范圍 Byte 存在 [-128,127] Short 存在 [-128,127] Integer 存在 [-128,127] Long 存在 [-128,127] Character 存在 [0,127] Float 不存在 無 Double 不存在 無 -
注意點:
- 當 "=="運算子的兩個運算元都是 包裝器型別的參考,則是比較指向的是否是同一個物件,而如果其中有一個運算元是運算式(即包含算術運算)則比較的是數值(即會觸發自動拆箱的程序)
- 對于包裝器型別,equals方法并不會進行型別轉換
- 算術運算會觸發裝箱與拆箱程序
文章為原創,轉載請宣告出處
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/35161.html
標籤:Java
