深刻理解 Java 基本數據類型

深刻理解 Java 基本數據類型

📓 本文已歸檔到:「bloghtml

數據類型分類

Java 中的數據類型有兩類:java

  • 值類型(又叫內置數據類型,基本數據類型)
  • 引用類型(除值類型之外,都是引用類型,包括 String、數組)

值類型

Java 語言提供了 8 種基本類型,大體分爲 4git

  • 整數型
    • byte - 8 位。
    • short - 16 位。
    • int - 32 位。
    • long - 64 位,賦值時通常在數字後加上 lL
  • 浮點型
    • float - 32 位,直接賦值時必須在數字後加上 fF
    • double - 64 位,賦值時通常在數字後加 dD
  • 字符型
    • char - 16 位,存儲 Unicode 碼,用單引號賦值。
  • 布爾型
    • boolean - 只有 true 和 false 兩個取值。

值類型和引用類型的區別

  • 從概念方面來講
    • 基本類型:變量名指向具體的數值。
    • 引用類型:變量名指向存數據對象的內存地址。
  • 從內存方面來講
    • 基本類型:變量在聲明以後,Java 就會馬上分配給他內存空間。
    • 引用類型:它以特殊的方式(相似 C 指針)向對象實體(具體的值),這類變量聲明時不會分配內存,只是存儲了一個內存地址。
  • 從使用方面來講
    • 基本類型:使用時須要賦具體值,判斷時使用 == 號。
    • 引用類型:使用時能夠賦 null,判斷時使用 equals 方法。

👉 擴展閱讀:Java 基本數據類型和引用類型github

這篇文章對於基本數據類型和引用類型的內存存儲講述比較生動。設計模式

數據轉換

Java 中,數據類型轉換有兩種方式:數組

  • 自動換行
  • 強制轉換

自動轉換

通常狀況下,定義了某數據類型的變量,就不能再隨意轉換。可是 JAVA 容許用戶對基本類型作有限度的類型轉換。post

若是符合如下條件,則 JAVA 將會自動作類型轉換:性能

  • 由小數據轉換爲大數據大數據

    顯而易見的是,「小」數據類型的數值表示範圍小於「大」數據類型的數值表示範圍,即精度小於「大」數據類型。設計

    因此,若是「大」數據向「小」數據轉換,會丟失數據精度。好比:long 轉爲 int,則超出 int 表示範圍的數據將會丟失,致使結果的不肯定性。

    反之,「小」數據向「大」數據轉換,則不會存在數據丟失狀況。因爲這個緣由,這種類型轉換也稱爲擴大轉換

    這些類型由「小」到「大」分別爲:(byte,short,char) < int < long < float < double。

    這裏咱們所說的「大」與「小」,並非指佔用字節的多少,而是指表示值的範圍的大小。

  • 轉換先後的數據類型要兼容

    因爲 boolean 類型只能存放 true 或 false,這與整數或字符是不兼容的,所以不能夠作類型轉換。

  • 整型類型和浮點型進行計算後,結果會轉爲浮點類型

示例:

long x = 30;
float y = 14.3f;
System.out.println("x/y = " + x/y);

輸出:

x/y = 1.9607843

可見 long 雖然精度大於 float 類型,可是結果爲浮點數類型。

強制轉換

在不符合自動轉換條件時或者根據用戶的須要,能夠對數據類型作強制的轉換。

強制轉換使用括號 ()

引用類型也可使用強制轉換。

示例:

float f = 25.5f;
int x = (int)f;
System.out.println("x = " + x);

裝箱和拆箱

包裝類、裝箱、拆箱

Java 中爲每一種基本數據類型提供了相應的包裝類,以下:

Byte <-> byte
Short <-> short
Integer <-> int
Long <-> long
Float <-> float
Double <-> double
Character <-> char
Boolean <-> boolean

引入包裝類的目的就是:提供一種機制,使得基本數據類型能夠與引用類型互相轉換

基本數據類型與包裝類的轉換被稱爲裝箱拆箱

  • 裝箱(boxing)是將值類型轉換爲引用類型。例如:intInteger
    • 裝箱過程是經過調用包裝類的 valueOf 方法實現的。
  • 拆箱(unboxing)是將引用類型轉換爲值類型。例如:Integerint
    • 拆箱過程是經過調用包裝類的 xxxValue 方法實現的。(xxx 表明對應的基本數據類型)。

自動裝箱、自動拆箱

基本數據(Primitive)型的自動裝箱(boxing)拆箱(unboxing)自 JDK 5 開始提供的功能。

JDK 5 以前的形式:

Integer i1 = new Integer(10); // 非自動裝箱

JDK 5 以後:

Integer i2 = 10; // 自動裝箱

Java 對於自動裝箱和拆箱的設計,依賴於一種叫作享元模式的設計模式(有興趣的朋友能夠去了解一下源碼,這裏不對設計模式展開詳述)。

👉 擴展閱讀:深刻剖析 Java 中的裝箱和拆箱

結合示例,一步步闡述裝箱和拆箱原理。

裝箱、拆箱的應用和注意點

裝箱、拆箱應用場景

  • 一種最普通的場景是:調用一個含類型爲 Object 參數的方法,該 Object 可支持任意類型(由於 Object 是全部類的父類),以便通用。當你須要將一個值類型(如 int)傳入時,須要使用 Integer 裝箱。
  • 另外一種用法是:一個非泛型的容器,一樣是爲了保證通用,而將元素類型定義爲 Object。因而,要將值類型數據加入容器時,須要裝箱。
  • == 運算符的兩個操做,一個操做數是包裝類,另外一個操做數是表達式(即包含算術運算)則比較的是數值(即會觸發自動拆箱的過程)。

示例:

Integer i1 = 10; // 自動裝箱
Integer i2 = new Integer(10); // 非自動裝箱
Integer i3 = Integer.valueOf(10); // 非自動裝箱
int i4 = new Integer(10); // 自動拆箱
int i5 = i2.intValue(); // 非自動拆箱
System.out.println("i1 = [" + i1 + "]");
System.out.println("i2 = [" + i2 + "]");
System.out.println("i3 = [" + i3 + "]");
System.out.println("i4 = [" + i4 + "]");
System.out.println("i5 = [" + i5 + "]");
System.out.println("i1 == i2 is [" + (i1 == i2) + "]");
System.out.println("i1 == i4 is [" + (i1 == i4) + "]"); // 自動拆箱
// Output:
// i1 = [10]
// i2 = [10]
// i3 = [10]
// i4 = [10]
// i5 = [10]
// i1 == i2 is [false]
// i1 == i4 is [true]

示例說明:

上面的例子,雖然簡單,但卻隱藏了自動裝箱、拆箱和非自動裝箱、拆箱的應用。從例子中能夠看到,明明全部變量都初始化爲數值 10 了,但爲什麼會出現 i1 == i2 is [falsei1 == i4 is [true]

緣由在於:

  • i一、i2 都是包裝類,使用 == 時,Java 將它們當作兩個對象,而非兩個 int 值來比較,因此兩個對象天然是不相等的。正確的比較操做應該使用 equals 方法。
  • i1 是包裝類,i4 是基礎數據類型,使用 == 時,Java 會將兩個 i1 這個包裝類對象自動拆箱爲一個 int 值,再代入到 == 運算表達式中計算;最終,至關於兩個 int 進行比較,因爲值相同,因此結果相等。

裝箱、拆箱應用注意點

  1. 裝箱操做會建立對象,頻繁的裝箱操做會形成沒必要要的內存消耗,影響性能。因此應該儘可能避免裝箱。
  2. 基礎數據類型的比較操做使用 ==,包裝類的比較操做使用 equals 方法。

小結

(1)Java 中的數據類型有兩類:

  • 值類型(byteshortintlongfloatdoublecharboolean
  • 引用類型(除值類型之外,都是引用類型,包括 String、數組)

(2)Java 中,數據類型轉換有兩種方式:

  • 自動換行
  • 強制轉換

強制轉換使用括號 ()

基礎數據類型能夠自動轉換,轉換原則以下:

  • 由小數據轉換爲大數據
  • 轉換先後的數據類型要兼容
  • 整型類型和浮點型進行計算後,結果會轉爲浮點類型

(3)包裝類有以下種類:

Byte <-> byte
Short <-> short
Integer <-> int
Long <-> long
Float <-> float
Double <-> double
Character <-> char
Boolean <-> boolean

(4)什麼是裝箱、拆箱

  • 裝箱(boxing)是將值類型轉換爲引用類型。例如:intInteger
    • 裝箱過程是經過調用包裝類的 valueOf 方法實現的。
  • 拆箱(unboxing)是將引用類型轉換爲值類型。例如:Integerint
    • 拆箱過程是經過調用包裝類的 xxxValue 方法實現的。(xxx 表明對應的基本數據類型)。

(5)裝箱、拆箱的應用場景

  • 含類型爲 Object 參數的方法
  • 非泛型的容器
  • == 運算符的兩個操做,一個操做數是包裝類,另外一個操做數是表達式(即包含算術運算)則比較的是數值(即會觸發自動拆箱的過程)。

(6)裝箱、拆箱的應用注意點

  • 裝箱操做會建立對象,頻繁的裝箱操做會形成沒必要要的內存消耗,影響性能。因此應該儘可能避免裝箱。
  • 基礎數據類型的比較操做使用 ==,包裝類的比較操做使用 equals 方法。

參考資料

相關文章
相關標籤/搜索