Java中的8個基本類型
數據類型 | boolean | byte | char | short | int | long | float | double |
---|---|---|---|---|---|---|---|---|
包裝類型 | Boolean | Byte | Character | Short | Integer | Long | Float | Double |
bit | 32 | 8 | 16 | 16 | 32 | 64 | 64 | 64 |
基本類型的兩條準則:
- 對整型數據不指定類型默認爲int類型,浮點數默認爲double類型
- 基本數據類型從小(字節)到大可以自動轉換,從大到小需要進行類型強制轉換(cast)
boolean類型會在編譯時期被JVM轉換爲int,true爲常量值1,false爲0,如
boolean a = true;
查看字節碼(javap -verbose xxx.class)會發現iconst_1指令,是指把int常量值1壓入棧中,因此boolean需要4個字節進行存儲。使用int的原因是對於當下32位的處理器(CPU)來說,一次處理數據是32位。而boolean數組會被編譯爲byte數組,故作爲數組時,數組中的每個boolean元素只佔一個字節。
基本類型都有對應的包裝類型,基本類型與包裝類型之間的轉換自動裝箱與拆箱完成:
Integer a = 5; // 裝箱調用Integer.valueOf(2)
int b = a; // 拆箱調用Integer.intValue()
在 Java 8 中,大部分基本類型都有緩存值,如Integer通過其內部類IntegerCache的cache[]緩存了-128~127範圍值。
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
...
}
當使用裝箱方式初始化Integer時,若初始值是在緩存範圍內,則會引用緩存範圍內的對象。從上源碼註釋可以看出,Integer可以通過在啓動jvm時添加-XX:AutoBoxCacheMax=<size>
設置其緩存大小,但其它基本類型是沒有相應的設置方式的。
Integer a = 5;
Integer b = 5;
System.out.println(a==b); //true
b = new Integer(5); // 爲5分配了新的空間,所以與緩存5的空間地址不同
System.out.println(a==b); //false
a = 255;
b = 255;
System.out.println(a==b); //false
各基本類型對應包裝類型的緩存池值(Double、Float沒有緩存)如下:
- Boolean: 通過字段緩存true,false
- Byte:內部類ByteCache緩存所有字節(-127-128)
- Short:內部類ShortCache緩存-127-128
- Integer:內部類IntegerCache緩存-127-128
- Long:內部類LongCache緩存-127-128
- Character:內部類CharacterCache緩存0~127對應的ASCII碼字符值
從字節數解讀不同位運算
char a = 'a'; // 'a'的ASCII碼爲97
int b = 13;
long e = a + d;
那麼問題來了,e是多少呢?運算過程中類型是怎麼轉換的呢?請務必讓我根據下圖一一講解:
(上圖爲在類編譯結果目錄target/pagkage執行javap -verbose Test顯示的字節碼)
- bipush將a轉換爲int值('a’對應的ASCII碼值)入棧,istore_1取出棧頂int值(即a值)保存到局部變量1中
- bipush將b(b本身爲int,無需轉換)入棧,istore_2取出棧頂int值(即b值)保存到局部變量2中
- iload_1、iload_2將局部變量1、2的int類型值入棧,iadd將棧頂的2個int值相加,並將結果壓棧,i2l將int轉long(不是i2十一哦),然後lstore_3將棧頂long值保存到局部變量3中
如果你問我知道這些有什麼用?第一反應肯定是裝逼啊[doge],當然對基本數據類型的運算了解肯定也會加深啦。