在Java中,總共有8種基本類型,其中4種整型,2種浮點(diǎn)型,char字符類型和boolean類型
整型
| 類型 | 存儲(chǔ)字節(jié) | 取值范圍 |
|---|---|---|
| int | 4字節(jié) | -2 147 483 648 ~ 2 147 483 647,-2^31 ~ 2^31-1 |
| short | 2字節(jié) | -32 768 ~ 32 767,-2^15 ~ 2^15-1 |
| long | 8字節(jié) | -9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807,-2^63 |
| byte | 1字節(jié) | -128 ~ 127,-2^7 ~ 2^7-1 |
- 在Java中,整型都有固定的取值范圍和字節(jié)長(zhǎng)度,且不受操作系統(tǒng)的影響,這就解決了軟件跨平臺(tái)的諸多問題
- 在Java中,整數(shù)有多種表現(xiàn)形式,分別是:
a. 十進(jìn)制整數(shù),如110,1111,233,0
b. 八進(jìn)制整數(shù),要求以0開頭(注意這是數(shù)字0,不是字母o),如010對(duì)應(yīng)八進(jìn)制中的8,顯然八進(jìn)制表示法比較容易混淆,所以建議最好不要使用八進(jìn)制常數(shù)。
c. 十六進(jìn)制整數(shù),要求以0x或0X開頭(注意這是數(shù)字0,不是字母o),如0x12就是18,0xCAFE就是51966
d. 從Java 7開始,加上前綴0b或0B(注意這是數(shù)字0,不是字母o),如0b1001就是9 - 通常情況下,int類型最常用,但是需求很大的數(shù)值時(shí),如表示星球上的居住人數(shù)時(shí)就緒使用long類型,long類型需要有一個(gè)后綴L或l,如4000000000L
- byte和short類型主要用于特殊場(chǎng)合,其中byte是8位的,有符號(hào)得,最大值就是2^7-1=127,二進(jìn)制為:0111 1111,而最小值為-2^7=-128,二進(jìn)制形式為:1000 0000,默認(rèn)值為0,綜合起來(lái)就是總長(zhǎng)度為2^8=256即:
0~127:128個(gè)
-0~127:128個(gè) - byte對(duì)應(yīng)的包裝類型為Byte,其使用Flyweight模式(享元模式)預(yù)先構(gòu)造了一個(gè)能表示所有byte類型數(shù)據(jù)的對(duì)象緩存,當(dāng)使用
valueOf(byte)進(jìn)行裝箱時(shí),會(huì)使用緩存的對(duì)象,但其構(gòu)造方法Byte(byte)/Byte(String)不會(huì)使用緩存對(duì)象,即存在:
Byte.valueOf((byte) 1) == Byte.valueOf("1"); // true
new Byte((byte) 1) == new Byte("1"); // false
Byte.decode("1") == Byte.decode("0x1"); // true,內(nèi)部調(diào)用 valueOf(byte)
- 整數(shù)運(yùn)算在JVM中只有兩套,一套用于int類型數(shù)據(jù),另一套用于long類型數(shù)據(jù),所以,所有的byte/char/short/int類型數(shù)據(jù)在運(yùn)算時(shí),均使用操作int類型數(shù)據(jù)的指令。如果操作數(shù)中沒有l(wèi)ong類型,則需要將所有的操作數(shù)提升為int類型進(jìn)行運(yùn)算(JVM中體現(xiàn)為所有指令均為int類型指令,運(yùn)算之前不會(huì)有提升的指令,直接采用int指令操作),運(yùn)算結(jié)果也是int類型的,如果需要窄化,需要強(qiáng)制類型轉(zhuǎn)換:
byte a = 1;
byte b = 1;
int c = a + b; // output:2
byte d = a + b; // error:Incompatible types.Required:byte Found:int
byte e = (byte)(a + b); // output:2
如果操作數(shù)中有l(wèi)ong型,則需要將所有的操作數(shù)提升為long類型進(jìn)行運(yùn)算(JVM中體現(xiàn)為所有指令均為long類型指令,但運(yùn)算之前需要使用i2l指令將int類型數(shù)據(jù)提升為long型數(shù)據(jù)),運(yùn)算結(jié)果為long型。
浮點(diǎn)類型
Java余元支持兩種基本的浮點(diǎn)類型:float和double,以及他們對(duì)應(yīng)的包裝類型 Float 和 Double。它們都依據(jù)IEEE 754標(biāo)準(zhǔn),該標(biāo)準(zhǔn)為32位浮點(diǎn)和64位雙精度浮點(diǎn)二進(jìn)制小數(shù)定義了二進(jìn)制標(biāo)準(zhǔn)。
IEEE 754 用科學(xué)記數(shù)法以底數(shù)為 2 的小數(shù)來(lái)表示浮點(diǎn)數(shù)。IEEE 浮點(diǎn)數(shù)用 1 位表示數(shù)字的符號(hào),用 8 位來(lái)表示指數(shù),用 23 位來(lái)表示尾數(shù),即小數(shù)部分。作為有符號(hào)整數(shù)的指數(shù)可以有正負(fù)之分。小數(shù)部分用二進(jìn)制(底數(shù) 2)小數(shù)來(lái)表示,這意味著最高位對(duì)應(yīng)著值 ?(2 -1),第二位對(duì)應(yīng)著 ?(2 -2),依此類推。對(duì)于雙精度浮點(diǎn)數(shù),用 11 位表示指數(shù),52 位表示尾數(shù)。如圖:

| 類型 | 存儲(chǔ)字節(jié) | 取值范圍 |
|---|---|---|
| float | 4字節(jié) | 大約 ±3.402 823 47E+38F(有效位數(shù)為6 ~ 7位) |
| double | 8字節(jié) | 大約 ±1.797 693 134 862 315 70E+308(有效位為15位) |
- double表示這種類型的數(shù)值精度是float類型的兩倍,所以double類型有雙精度數(shù)值的說法。在通常情況下,應(yīng)該采用double類型,因?yàn)槎鄶?shù)情況下,float類型的精度很難滿足需求,除非需要單精度數(shù)據(jù)的庫(kù),或者需要存儲(chǔ)大量的數(shù)據(jù)
- float類型的數(shù)值有個(gè)后綴F或者f(例如,3.14F),沒有后綴的浮點(diǎn)數(shù)值(如3.14)默認(rèn)為double類型。
- 所有的浮點(diǎn)數(shù)值計(jì)算都遵循IEEE754規(guī)范。用于表示溢出和出錯(cuò)情況的三個(gè)特殊的浮點(diǎn)數(shù)值:
- 正無(wú)窮大,對(duì)應(yīng)常量 Double.POSITIVE_INFINITY
- 負(fù)無(wú)窮大,對(duì)應(yīng)常量 Double.NEGATIVE_INFINITY
- NaN(不是一個(gè)數(shù)字),對(duì)應(yīng)常量 Double.NaN
- 浮點(diǎn)型的運(yùn)算指令也有兩套,當(dāng)操作符兩段的數(shù)據(jù)均為float型時(shí),使用float對(duì)應(yīng)的運(yùn)算指令,若操作數(shù)兩段的數(shù)據(jù)有double型,則需要插入
f2d指令將float型數(shù)據(jù)提升為double型:
float a = 0.1f, b = 0.2f
double c = 1.2;
double d = a * b * c; // 產(chǎn)生的指令相當(dāng)于 ((double)(a * b)) * c
double e = c * a * b; // 產(chǎn)生的指令相當(dāng)于 c * ((double)a) * ((double)b)
- 對(duì)于整型和浮點(diǎn)型數(shù)據(jù)的混合運(yùn)算,如果運(yùn)算符兩端均為整型,則使用整型指令運(yùn)算,否則使用浮點(diǎn)數(shù)運(yùn)算指令:
int a = 1, b = 2;
double c = 2.3;
double d = a * b * c; // 產(chǎn)生的指令相當(dāng)于 ((double)(a * b)) * c
double e = c * a * b; // 產(chǎn)生的指令相當(dāng)于 c * ((double)a) * ((double)b)
綜上所述,整型和浮點(diǎn)數(shù)運(yùn)算過程中數(shù)據(jù)類型都是以運(yùn)算符兩端最高操作數(shù)類型為標(biāo)準(zhǔn),將次等級(jí)的操作數(shù)類型提升為最高類型后進(jìn)行運(yùn)算,具體的提升方向?yàn)椋?/p>
- INTEGRAL - > long, INTEGRAL -> float, INTEGRAL -> double
- long -> float, long -> double
- float -> double
char類型
char類型原本用于表示單個(gè)字符。但是現(xiàn)在Unicode字符可以用一個(gè)char值描述,而另一些Unicode字符則需要兩個(gè)char值,char類型的字面量要用單引號(hào)括起來(lái),如:'A'是編碼值為65所對(duì)應(yīng)的字符常量。它與"A"不同,"A"是包含一個(gè)字符A的字符串。char類型的值可以表示為十六進(jìn)制值,其范圍為\u0000到\Uffff。
在Java中,char類型描述了UTF-16編碼中的一個(gè)代碼單元(所以要了解char需要先弄明白Unicode和UTF-16相關(guān)知識(shí),請(qǐng)看這里),所以在 Java 中 char 數(shù)據(jù)類型是定長(zhǎng)的,其長(zhǎng)度永遠(yuǎn)只有 16 位,char 數(shù)據(jù)類型永遠(yuǎn)只能表示代碼點(diǎn)在 U+0000 ~ U+FFFF 之間的字符,也就是在 BMP 內(nèi)的字符。如果代碼點(diǎn)超過了這個(gè)范圍,即使用了增補(bǔ)字符,那么 char 數(shù)據(jù)類型將無(wú)法支持,因?yàn)樵鲅a(bǔ)字符需要 32 位的長(zhǎng)度來(lái)存儲(chǔ),我們只能轉(zhuǎn)而使用 String 來(lái)存儲(chǔ)這個(gè)字符。
char c1 = '??';
char c2 = '\u64321';
如上編寫的代碼,使用 char 數(shù)據(jù)類型來(lái)保存輔助平面的字符,編譯器將會(huì)報(bào)錯(cuò) Invalid character constant。
boolean類型
boolean類型有兩個(gè)值:false和true,但是在Java虛擬機(jī)中沒有任何供boolean值專用的字節(jié)碼指令。根據(jù)《Java虛擬機(jī)規(guī)范》的描述:
雖然定義了boolean這種數(shù)據(jù)類型,但是只對(duì)它提供了非常有限的支持。在Java虛擬機(jī)中沒有任何供boolean值專用的字節(jié)碼指令,Java語(yǔ)言表達(dá)式所操作的boolean值,在編譯之后都使用Java虛擬機(jī)中的int數(shù)據(jù)類型來(lái)代替,而boolean數(shù)組將會(huì)被編碼成Java虛擬機(jī)的byte數(shù)組,每個(gè)元素boolean元素占8位
所以在談及boolean類型占用的存儲(chǔ)空間,可能最合理的是4字節(jié),在數(shù)組中又是1個(gè)字節(jié)
參考
- 《Java核心技術(shù) 卷I 基礎(chǔ)知識(shí)》
- Java 7之基礎(chǔ)類型第1篇 - Java數(shù)據(jù)類型
- 深入理解Java基本數(shù)據(jù)類型
- 您的小數(shù)點(diǎn)到哪里去了?
- Java 中 char 和 String 的細(xì)節(jié)和使用注意