4、Java基本資料型別
1、基本資料型別
JAVA中一共有八種基本資料型別,他們分別是 byte、short、int、long、float、double、char、boolean
型別 | 型別 | 位元組 | 取值範圍 |
---|---|---|---|
byte | 整型 | -27 ~ 27-1 | |
short | 整型 | 2byte | -215 ~ 215-1 |
int | 整型 | 4byte | -231 ~ 231-1 |
long | 整型 | 8byte | -263 ~ 263-1 |
float | 浮點型 | 4byte | 3.402823e+38 ~ 1.401298e-45 |
double | 浮點型 | 8byte | 1.797693e+308~ 4.9000000e-324 |
char | 文字型 | 2byte | 0~216-1 |
boolean | 布林型 | 1byte | true/false |
在通常情況下,如果JAVA中出現了一個整數數字比如35,那麼這個數字就是int型的。如果我們希望它是byte型的,可以在資料後加上大寫的 B:35B,表示它是byte型的。同樣的35S表示short型,35L表示long型的,表示int我們可以什麼都不用加,但是如果要表示long型的,就一定要在資料後面加“L”。
double型比float型儲存範圍更大,精度更高,所以通常的浮點型的資料在不宣告的情況下都是double型的,如果要表示一個數據是float型的,可以在資料後面加上“F”。 浮點型的資料是不能完全精確的,所以有的時候在計算的時候可能會在小數點最後幾位出現浮動,這是正常的。
2、自動型別轉換
1)兩種型別是彼此相容的
2)轉換後的目標型別佔的空間範圍一定要大於被轉化的源型別
由低位元組向高位元組自動轉換(黑線表示無資料丟失的自動資料轉換,紅線表示轉換中可能發生精度丟失)
<關於int轉float發生精度丟失,而int轉double可以無資料丟失,可自行研究。
3、強制資料轉換
將容納更多資訊的資料型別轉換成一個容量更小的資料型別,可能存在精度損失的風險,編譯器要求程式設計師進行強制型別轉換。
強制轉換過程中可能發生資料溢位,必須警惕。
int a=(int)3.14;
4、資料型別自動提升
如果兩個運算元其中有一個是double型別,另一個操作就會轉換為double型別。
否則,如果其中一個運算元是float型別,另一個將會轉換為float型別。
否則,如果其中一個運算元是long型別,另一個會轉換為long型別。
否則,兩個運算元都轉換為int型別。
5、大資料型別
如果基本的整數和浮點數精度不夠滿足需求,那麼可以使用java.math包中的兩個很有用的類:BigInteger和BigDecimal。這兩個類可以處理包含任意長度數字序列的數值,BigInteger類實現了任意精度的整數運算,BigDecimal實現了任意精度的浮點數運算。 使用靜態的valueOf方法可以將普通的數值轉換為大數值:
BigInteger a = BigInteger.valueOf(100);
二、基本型別對應的包裝類
1、概述
雖然 Java 語言是典型的面向物件程式語言,但其中的八種基本資料型別並不支援面向物件程式設計,基本型別的資料不具備“物件”的特性——不攜帶屬性、沒有方法可呼叫。 沿用它們只是為了迎合人類根深蒂固的習慣,並的確能簡單、有效地進行常規資料處理。 這種藉助於非面向物件技術的做法有時也會帶來不便,比如引用型別資料均繼承了 Object 類的特性,要轉換為 String 型別(經常有這種需要)時只要簡單呼叫 Object 類中定義的toString()即可,而基本資料型別轉換為 String 型別則要麻煩得多。為解決此類問題 ,Java為每種基本資料型別分別設計了對應的類,稱之為包裝類(Wrapper Classes),也有教材稱為外覆類或資料型別類。
基本資料型別對應的包裝類如下圖:
2、裝箱和拆箱
2.1、什麼是裝箱和拆箱?
前面已經提到了,JAVA為每一個基本資料型別都提供了一個包裝器類,在JAVA SE5之前,如果要生成一個數值為10的Integer物件,需要這麼做:
Integer integer = new Integer(10); 而在JAVA SE5開始就提供了自動裝箱功能,如果要生成數值為10的Integer物件,只需要像下面這樣做就行了:
Integer integer = 10; 這樣寫會觸發自動裝箱,能直接根據數值就能建立對應的Integer物件,而不用new操作。
那麼拆箱是怎麼樣的呢?只需要像下面這樣做就行了:
Integer integer = 5;//裝箱 int i = integer;//拆箱 簡而言之,裝箱就是基本資料型別轉換為包裝器型別,拆箱就是包裝器型別轉換基本型別。
2.2、裝箱和拆箱的過程是什麼?
通過上面的介紹,知道了什麼是裝箱何拆箱。不過裝箱和拆箱的具體過程是什麼呢?其實裝箱和拆箱是呼叫了兩個函式來實現的,下面通過一段程式碼來說明:
public class Main {
public static void main(String[] args) {
Integer integer = 5;
int i = integer;
}
}
反編譯這段程式碼生成的class檔案:
從反編譯的結果來看,裝箱的時候呼叫了Integer.valueOf(int i)這個函式,拆箱的時候呼叫了Integer.intValue()這個函式。
總的來說,裝箱的時候是呼叫的包裝器的valueOf這個函式,拆箱的時候呼叫的是包裝器的xxxValue這個函式(xxx是包裝器對應的基本資料型別)。
2.3、裝箱和拆箱關鍵原始碼分析
通過上面的介紹,我們知道了裝箱和拆箱關鍵在於valueOf和xxxValue這兩個函式,xxxValue這個函式沒有什麼值得注意的,就是把包裝器中的值裝換為對應的基本資料型別。而valueOf這個函式在不同的包裝器中,實現方法有很大的區別。
下面,先介紹在Integer包裝器類中,該方法是怎麼實現的,原始碼如下:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
private static class IntegerCache {
static final int high;
static final Integer cache[];
static {
final int low = -128;
// high value may be configured by property
int h = 127;
if (integerCacheHighPropValue != null) {
// Use Long.decode here to avoid invoking methods that
// require Integer's autoboxing cache to be initialized
int i = Long.decode(integerCacheHighPropValue).intValue();
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - -low);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}