壁咚Java 詳解Java基本數據類型

[toc]html

數據類型的出現是爲了把數據分紅所需內存大小不一樣的數據,合理、有效利用內存。數據類型在計算機語言裏面,是對內存位置的一個抽象表達方式。java

數據類型

在JAVA語言種將數據類型分爲兩類:基本數據類型引用數據類型 面試

數據類型

  • 基本類型:簡單數據類型是不能簡化的、內置的數據類型、由編程語言自己定義,它表示了真實的數字、字符和整數。
  • 引用數據類型:Java語言的引用數據類型包括類、接口和數組類型,還有一種特殊的null類型。引用數據類型是對一個對象的引用,對象有兩種:數組和實例(面向對象的基本知識點,這篇文章主要以基本數據類型爲主)

基本數據類型

基本數據類型分爲4類,分別爲整型、浮點型、字符型和布爾型編程

整型

Java從入門到精通

1字節=8位

4種整型量都是有符號的,符號佔一位(byte的取值範圍本該是2的8次方,其餘相似)。數組

Java整數常量默認是int類型

下表能夠清楚的看出每一個取值範圍內可使用的數據類型(這裏沒有把負數部分畫出來)緩存

取值範圍 0~127 128 ~ 32767 32768 ~ 2147483647 2147483648 ~ 9223372......
數據類型 byte、short、int、long short、int、long int、long long
  • byte、short可使用在其取值範圍內的整數常量,系統自動把這些整數常量當成byte或short類型處理。使用超出範圍的整數常量會報錯。
byte b = 127;
  byte b2 = 128;//報錯:Required:byte Found:int(默認是int類型)
複製代碼
  • 若是把一個超出int取值範圍的整數常量賦值給long類型,會報錯;強制使用long類型須要在整數常量後加L(或l)
  • 若是把一個int範圍內的整數常量賦值給long類型,不會報錯,是由於發生了自動類型轉換(下面會具體說明)
int num1 = 2147483647;
 long l1 = 2147483647;//正常,發生了自動類型轉換
 int num2 = 2147483648;//報錯: Integer number too
 large
 long l2 = 2147483648;//報錯: Integer number too
 large 
 long l3 = 2147483648L;//正常
 
複製代碼

整數常量的四種表示方式

  1. 二進制:0b或0B開頭(java7開始支持)
  2. 八進制:0開頭
  3. 十進制:不作過多說明
  4. 十六進制:0x或0X開頭
int num1=013;//八進制
int num2=0x13;//十六進制
複製代碼

重點說明二進制表示方式安全

全部數字在計算機底層都是以二進制形式表示的,原碼是直接將一個數值換算成二進制數。計算機是以補碼形式保存全部的整數。正數的補碼和原碼徹底相同,負數的補碼是原碼的反碼加1;反碼是對原碼按位取反,最高位符號位不變。併發

Java瘋狂講義

  • 二進制整數的最高位是符號位,1表示負數,0表示正數
  • java整數常量默認是int類型,因此二進制整數默認佔32位,定義一個不足位的二進制整數時,會自動高位補齊(補0),第32位是符號位
  • 系統對byte、short類型的使用與十進制一致
  • 使用long類型須要在末尾加L(或l),表示佔64位,第64位是符號位

關於進制間的轉換請看 進制間的轉換 這篇文章編程語言

浮點型

Java從入門到精通

  • float(單精度浮點型):第1位是符號位,接下來8位表示指數,其他23位表示尾數
  • double(雙精度浮點型):第1位符號位,接下來11位表示指數,其他52位表示尾數

浮點數的兩種表示方式

  1. 十進制數形式,float浮點數後加F(或f),double浮點數後加D(或d),浮點數必須包含一個小數點,性能

    float f=5.1200_001f;//可使用_分隔,方便校對數位

  2. 科學計數法形式,只有浮點型的數值可使用科學計數法形式表示。如:5.12E2(5.12✖️10^2)

字符型

  • java語言使用16位的Unicode字符集(關於字符編碼問題請看阮一峯的字符編碼筆記)做爲編碼方式
  • char類型的取值範圍是0~2^16(65536),是無符號的整數(正數),能夠被用做整數類型的值來使用,一樣系統也會把整數類型的值當成char類型處理

字符型常量的三種表示方式

  1. 直接經過單個字符來指定,如 'a','0'
  2. 經過轉義字符表示特殊字符型常量

經常使用轉義字符

Java從入門到精通

  1. 直接使用Unicode值表示字符型常量,範圍'\u0000'-'\uFFFF',其中前256個('\u0000'-'\u00FF')字符和ASCII碼錶中的字符安完成重合

布爾型

用於表示邏輯上的」真「或」假「

基本類型的類型轉換

自動類型轉換

取值範圍小的類型賦值給取值範圍大的類型,系統自動進行類型轉換,如圖所示,能夠根據箭頭指向發生自動轉換

自動轉換

強制類型轉換

強制類型轉換可能會丟失精度,因此須要使用()進行類型轉換。

Java瘋狂講義

32位int型最高位0表示正數,轉換爲byte類型,高位精度丟失,第8位爲byte最高位,1表示負數,所以正數的int型因丟失精度變成了負數的byte型。

表達式類型的自動提高

當一個算術表達式中包含多個基本類型的值時,整個算術表達式的數據類型將發生自動提高

  • byte、short、char自動提高爲int類型
  • 整個表達式的數據類型自動提高到與表達式中最高等級操做數的數據類型
  • 與字符串拼接規則:字符串在+號的左邊,表示字符串拼接,若是字符串在+號的右邊要具體看左邊的狀況
System.out.println("Hello" + 'a' + 7);//Helloa7
  System.out.println('a' + 7 + "Hello");//104Hello
複製代碼

包裝類

Java瘋狂講義

爲何還須要包裝類

Java中的int類型在內存中只佔用4個字節,而一個Object對象自己最少佔用8個字節,另外還須要4個字節來引用它。除此以外CPU對基本類型的處理更加高效。

既然如此爲何還須要包裝類?

Java是面向對象的編程語言,但這8種基本數據類型並不支持面試對象的特性。因此 Java 須要一個這樣的包裝類來使其面向對象的完整性,這樣一來基本類型具備了對象的特性,例如:實現可空類型,完成字符串像基本類型的轉換,另外Java 集合中只能放入包裝類型,不支持基本類型。

//可爲空
        Integer integer=null;
        //字符串轉換爲int型
        int num=Integer.valueOf("123");
        //java集合只能放入Integer類型,沒法放入int類型
        ArrayList<Integer> arrayList=new ArrayList<>();
複製代碼

緩衝池——減小內存開銷,提升程序性能

Integer integer = Integer.valueOf(127);
 int intValue = integer.intValue();
複製代碼
  • 經過靜態方法valueOf將基本類型包裝爲Integer類型
  • 經過intValue方法將包裝類轉換爲int類型。
private final int value;
    //intValue方法比較簡單,直接返回value
    public int intValue() {
        return value;
    }
    //valueOf方法的內部實現
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
複製代碼

能夠從valueOf方法內部看到,傳入進來的i並非直接調用new Integer(i)來建立對象的,而是經過IntegerCache.cache緩存中獲取的。

IntegerCache是Integer的一個內部類

private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }
複製代碼

從上面的代碼中,能夠看到IntegerCache類中聲明瞭Integer cache[]數組來緩存Integer對象的,而且IntegerCache.lowIntegerCache.high常量肯定了cache的範圍從-128~127,也就是說不在這個範圍內的值,會直接經過new Integer(i)來建立對象。

Integer num1 = 127;
        Integer num2 = 127;
        System.out.println(num1 == num2);//引用的同一個對象因此輸出爲 true
        
        Integer num1 = 128;
        Integer num2 = 128;
        System.out.println(num1 == num2);//超出了緩存範圍輸出false 
        
        Integer integer1 = new Integer(127);
        Integer integer2 = new Integer(127);
        System.out.println(integer1 == integer2);//直接new的對象,未走緩存輸出false
複製代碼

在int和Integer類型之間轉換其實不須要如此的麻煩,從java5開始爲咱們提供了裝箱和拆箱的操做,簡化轉換過程。

自動裝箱、拆箱——只是一種語法糖

Integer a= 123;     // 裝箱
int b = a;         // 拆箱
複製代碼

裝箱和拆箱能夠當作一種java語法糖,javac編譯器會自動把裝箱轉換爲Integer.valueOf(),把拆箱轉換爲Integer.intValue(),所以咱們在使用裝箱時依然可使用Integer的緩存。

成員變量value的不可變性

包裝類的成員變量value都使用了final關鍵字修飾,這代表它們是不可變類型(常量)。

對於成員變量value只須要明白3點就能夠了

  1. 它的訪問修飾符是pirvate,因此外部沒法修改它
  2. 使用了final關鍵字修飾,內部一旦賦值便沒法再改變
  3. 基本數據類型的不可變性知足上面兩點就能夠了,不像引用類型,被final修改後,引用自己不可變,但具體的實例是能夠經過引用改變的。這點在String類型中詳細說明(String是經過copyOf()方法來保證不可變的)

之因此設計成不可變的的目的是爲了保證基本的信息安全和併發環境下的線程安全

其餘基本類型的包裝類

  • Boolean,緩存了true/false對應實例
  • Short,緩存範圍與Integer一致
  • Byte,所有緩存
  • Character,緩存範圍'\u0000' ~ '\u007F'
  • Double和Float類型沒有使用緩存池
相關文章
相關標籤/搜索