問我Java基本數據類型?我可以把字節碼也扯上了

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是多少呢?運算過程中類型是怎麼轉換的呢?請務必讓我根據下圖一一講解:
%E5%AD%97%E8%8A%82%E7%A0%81.png
(上圖爲在類編譯結果目錄target/pagkage執行javap -verbose Test顯示的字節碼)

  1. bipush將a轉換爲int值('a’對應的ASCII碼值)入棧,istore_1取出棧頂int值(即a值)保存到局部變量1中
  2. bipush將b(b本身爲int,無需轉換)入棧,istore_2取出棧頂int值(即b值)保存到局部變量2中
  3. iload_1、iload_2將局部變量1、2的int類型值入棧,iadd將棧頂的2個int值相加,並將結果壓棧,i2l將int轉long(不是i2十一哦),然後lstore_3將棧頂long值保存到局部變量3中

如果你問我知道這些有什麼用?第一反應肯定是裝逼啊[doge],當然對基本數據類型的運算了解肯定也會加深啦。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章