Java有兩種有效的數(shù)據(jù)類型:
- 基本(Primitive)數(shù)據(jù)類型(也稱為原始數(shù)據(jù)類型)
- 引用數(shù)據(jù)類型:封裝類(Warpper)的引用
8種基本數(shù)據(jù)類型:
基本類型 | 名稱 | 封裝類 | 字節(jié)數(shù) | 最大值 | 最小值 | 緩存范圍 |
---|---|---|---|---|---|---|
byte | 字節(jié)型 | Byte | 1byte | 2^7 - 1 | -2^7 | -128~127 |
char | 字符型 | Character | 2byte |
\uffff (2^16 - 1) |
\u0000 (0) |
0~127 |
short | 短整型 | Short | 2byte | 2^15 - 1 | -2^15 | -128~127 |
int | 整型 | Integer | 4byte | 2^31 - 1 | -2^31 | -128~127 |
float | 單精度浮點型 | Float | 4byte | 3.4e+38 | 1.4e-45 | 無緩存 |
long | 長整型 | Long | 8byte | 2^63 - 1 | -2^63 | -128~127 |
double | 雙精度浮點型 | Double | 8byte | 1.8e+308 | 4.9e-324 | 無緩存 |
boolean | 布爾型 | Boolean | 不明確 | - | - | false、true |
- byte:1byte為8bits,常用于將Object轉(zhuǎn)換為byte[]數(shù)組,用于字節(jié)流ByteArrayInputStream的輸入
- char:Java最初設(shè)計
char
和Character
能保存所有的Unicode字符,所以設(shè)計為2個字節(jié)。但現(xiàn)在Unicode包含的字符越來越多,已經(jīng)收錄超過13萬個字符了(截止版本12.0.0)。char可以存放中文字符。Character c = '顏'; System.out.println(c.BYTES); //2
- boolean:Java虛擬機規(guī)范沒有明確規(guī)定boolean的字節(jié)數(shù),可能為1個字節(jié),也可能為4個字節(jié)。
Java編程語言中對布爾值進行操作的表達(dá)式被編譯為使用Java虛擬機int數(shù)據(jù)類型的值。
在Oracle的Java虛擬機實現(xiàn)中,Java編程語言中的布爾數(shù)組被編碼為Java虛擬機字節(jié)數(shù)組,每個布爾元素使用8位。 - Byte和Boolean類型緩存了全部值,緩存值存放在數(shù)組中。
- 封裝類被final修飾,基本數(shù)據(jù)類型也算是final修飾。
基本數(shù)據(jù)類型與封裝類的聯(lián)系
JDK5.0開始提供自動封箱功能,基本數(shù)據(jù)類型可以自動封裝成封裝類。
比如集合List,往里添加對象Object,JDK5.0以前需要將數(shù)字封裝成封裝類型對象,再存到List中。
List list = new ArrayList();
list.add(new Integer(1));
在JDK5.0 以后可以自動封箱,簡寫成:
List list = new ArrayList();
list.add(1);
也可以自動拆箱,將封裝器類型自動轉(zhuǎn)換為對應(yīng)的基本數(shù)據(jù)類型:
Integer a = 1;//裝箱,底層實現(xiàn):Integer a = Integer.valueOf(1);
int b = a; //拆箱,底層實現(xiàn):int b = a.intValue();
ASM Bytecode Outline
反編譯結(jié)果:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Integer i1 = 55;
Integer i2 = 55;
System.out.println(i1 == i2); //true
cache數(shù)組緩存了[-128,127]一共256個Integer對象,當(dāng)i滿足條件時,返回堆中對應(yīng)的Integer對象,否則新創(chuàng)建對象。i1、i2均指向同一個對象。
基本數(shù)據(jù)類型與其封裝類的區(qū)別
1、默認(rèn)值不同
int是基本類型,直接存放數(shù)值;Integer是類,產(chǎn)生對象時用一個引用指向這個對象。
基本類型跟封裝類型的默認(rèn)值是不一樣的。如int i,i的預(yù)設(shè)為0;Integer j,j的預(yù)設(shè)為null,因為封裝類產(chǎn)生的是對象,對象默認(rèn)值為null。
int i = 0;
float f = 0f;
double d = 0d;
System.out.println(i);//0
System.out.println(f);//0.0
System.out.println(d);//0.0
2、存儲位置不同
基本類型在內(nèi)存中是存儲在Java虛擬機棧中,封裝類的引用(值的地址)存儲在Java虛擬機棧中,而實際的對象(值)是存在堆中。
3、作用不同
基本數(shù)據(jù)類型的好處就是速度快(在棧上分配內(nèi)存效率高,且不涉及到對象的構(gòu)造和回收),封裝類的目的主要是更好的處理數(shù)據(jù)之間的轉(zhuǎn)換(利用其方法和屬性)。
常用小技巧
- 利用intValue()方法取整:
Float a = 5.2f;
System.out.println(a.intValue());
封裝類應(yīng)用場景
封裝類常用于接受參數(shù),當(dāng)不傳參數(shù)時,參數(shù)為null。
public void setTimeout(Integer timeout) {
this.timeout = timeout;
}
reference.setTimeout(20000);
需注意
要注意自動拆箱出現(xiàn)空指針異常:
List<Integer> list = new ArrayList<Integer>(3);
list.add(0);
list.add(1);
list.add(null);
for (int n:list){
System.out.println("n="+n);
}
Exception in thread "main" java.lang.NullPointerException
當(dāng)方法重載時,考慮Java向前兼容,不自動裝箱,而精準(zhǔn)匹配。所以下面輸出long num
。
public class BugInOverloading{
public static void test(Integer num){
System.out.println("Integer num");
}
public static void test(long num){
System.out.println("long num");
}
public static void main(String[] args) {
test(1);
}
}