老王的JAVA基礎課:第6課 基本數據類型

在這裏插入圖片描述

什麼是基本數據類型

這節課我們來學習java的基本數據類型,首先來看Q&A:
Q: 何謂數據類型?
A: 程序的本質是處理各種數據,在計算機底層來講數據本身沒有類型。而數據類型則表示一個數據是以什麼類型來表示。
Q: 何謂基本?
A: java中最基礎的數據類型,存在於棧內存(死記硬背,以後會講含義)。僅包含數據,可直接使用。與之相對的爲引用類型(以後會講到)。

JAVA基本數據類型

計算機中數據的最小單位是比特(bit),由於計算機系統的電路設計它只能表示爲0或1,8個比特位組成一個字節(byte),byte是數據存儲的最小單位。以下是java中基本數據類型以及各類型取值範圍。

數據類型 類型區分 佔用空間 默認值 取值範圍
byte 整形 1字節 0 -2^7 ~ 2^7-1
short 整形 2字節 0 -2^15 ~ 2^15-1
int 整形 4字節 0 -2^31 ~ 2^31-1
long 整形 8字節 0L -2^63 ~ 2^63-1
float 浮點型 4字節 0.0F 3.4e+38 ~ 1.4e-45
double 浮點型 8字節 0.0D 1.8e+308 ~ 4.9e-324
char 字符型 2字節 0 0 ~ 2^16-1
boolean 布爾型 1字節 false true/false

以上內容非常簡單,前三列記住即可。你可能疑惑爲什麼取值範圍都是亂七八糟的。現在來學習爲什麼取值範圍都不是我們預料的整數。

整形數據在內存中的表示

我們前面提到byte是數據存儲的最小單位,而byte作爲基本數據類型的一種,它的長度就是1byte,而1byte=8bit。以byte爲例,byte在內存中表示如下:
在這裏插入圖片描述
整形數據的最高位爲符號位,0表示正數,1表示負數。後面的bit爲數據位,byte可以表示7個數據位長度的數據。那麼7個數據位可以表示的正數範圍如下:
在這裏插入圖片描述
我們知道1bit最大隻能表示1,那麼2bit最大可以表示2^1+1 = 3,以此類推7位可表示的最大值爲上圖中依次相加,就等於2^7-1,也即十進制的127。在計算機中,數據的表示都是以“補碼”展現,正數的補碼是其本身(本身又叫“原碼”),而負數的補碼需要將原碼除符號位之外的每一位取反(0變成1,1變成0)後得到反碼,然後加1,略微複雜。初學可能不太好理解,在後續的課程中會推出專門的課題來介紹原碼、補碼、以及反碼。

由以上得知負數的補碼爲原碼除符號位外按位取反後+1,我們來看byte1類型的-1在內存中是如何表示的:在這裏插入圖片描述
因爲負數的符號位爲1,所以-1的原碼爲10000001,符號位不變,其他位取反得到反碼11111110,而補碼爲反碼+1,那麼-1的補碼錶示11111111。大家可能會注意到整形數據的最大值和最小值的絕對值並不是一樣的,例如byte的最大值爲127,而最小值爲-128,這是怎麼做到的呢?

注意到+0表示爲00000000,而-0可以表示爲10000000。但在現實中+0與-0都是表示0。爲了不必要的浪費。在計算機系統中,10000000表示爲最小值,如果是byte那麼最小值就表示爲-128.

由此我們可以推演到short、int、long都是如此。

float與double類型

float爲單精度浮點型數據類型,double爲雙精度浮點型數據類型。這兩種類型都可以表示小數,實際上只有精度和取值範圍區別。切記不可用於貨幣等關鍵數據的處理,因爲浮點型數據無法表示準確地表示一個小數(同樣以後再講)。float的默認值爲0.0f,而double的默認值爲0.0d。注意最後的f和d。示例:

float data1 = 1.2f;
double data2 = 2.34d;

char類型

char類型是一個單一的 16 位 Unicode 字符,注意其不存在符號位(最高位也是數據位),所以其範圍爲0~2^16-1(65535)。char可以存儲任何字符,注意其存儲的是字符數據而非整形數據。假如我們以如下方式賦值,輸出結果並不是想當然的65,如下:

char c = 65;
System.out.println(c);

-----------輸出結果-------------
A

這是因爲65在Unicode中表示A這個字符,如果我們想賦值A到char c,我們可以使用單引號括起來。

char c = 'A';
System.out.println(c);

-----------輸出結果-------------
A

boolean類型

在Java中所有基本類型都有一個與之對應的類。比如int類型對應Integer類,double類型對應Double類。這些類被稱爲包裝器類(wrapper)。Java有8種基本類型,有9個包裝器,分別爲:Intger、Long、Short、Byte、Double、Float、Character、Boolean以及Void。

那麼問題又來了,爲什麼需要包裝器類型?我們知道基本數據類型僅包含了數據,在實際開發中其他系統可能傳入一個數值過來,如果使用基本數據類型我們無從判斷這個值是否存在。這個時候必須要用到包裝器類型,因爲包裝器類型允許值爲null,可以通過值是否爲null來判斷這個值是否真實存在。另外包裝器類型提供了許多便捷的方法,避免我們重複造輪子。

以下是各數據類型的基礎示例:

public class TestDataType {

  public static void main(String[] args) {
   // byte
   System.out.println("基本數據類型byte 所佔bit數:" + Byte.SIZE);
   System.out.println("byte的包裝器類型爲:java.lang.Byte");
   System.out.println("最小值:" + Byte.MIN_VALUE);
   System.out.println("最大值:" + Byte.MAX_VALUE);
   System.out.println("-------------------------------------------");

   // short
   System.out.println("基本數據類型short 所佔bit數:" + Short.SIZE);
   System.out.println("short的包裝器類型爲:java.lang.Short");
   System.out.println("最小值:" + Short.MIN_VALUE);
   System.out.println("最大值:" + Short.MAX_VALUE);
   System.out.println("-------------------------------------------");

   // int
   System.out.println("基本數據類型int 所佔bit數:" + Integer.SIZE);
   System.out.println("int的包裝器類型爲:java.lang.Integer");
   System.out.println("最小值:" + Integer.MIN_VALUE);
   System.out.println("最大值:" + Integer.MAX_VALUE);
   System.out.println("-------------------------------------------");

   // long
   System.out.println("基本數據類型long 所佔bit數:" + Long.SIZE);
   System.out.println("long的包裝器類型爲:java.lang.Long");
   System.out.println("最小值:" + Long.MIN_VALUE);
   System.out.println("最大值:" + Long.MAX_VALUE);
   System.out.println("-------------------------------------------");

   // float
   System.out.println("基本數據類型float 所佔bit數:" + Float.SIZE);
   System.out.println("float的包裝器類型爲:java.lang.Float");
   System.out.println("最小值:" + Float.MIN_VALUE);
   System.out.println("最大值:" + Float.MAX_VALUE);
   System.out.println("-------------------------------------------");

   // double
   System.out.println("基本數據類型double 所佔bit數:" + Double.SIZE);
    System.out.println("double的包裝器類型爲:java.lang.Double");
   System.out.println("最小值:" + Double.MIN_VALUE);
   System.out.println("最大值:" + Double.MAX_VALUE);
    System.out.println("-------------------------------------------");

   // char
   System.out.println("基本數據類型char 所佔bit數:" + Character.SIZE);
   System.out.println("char的包裝器類型爲:java.lang.Character");
   // 以數值形式輸出
    System.out.println("最小值:" + (int) Character.MIN_VALUE);
   System.out.println("最大值:" + (int) Character.MAX_VALUE);
  }
}

編譯執行後輸出:

基本數據類型byte 所佔bit數:8
byte的包裝器類型爲:java.lang.Byte
最小值:-128
最大值:127
-------------------------------------------
基本數據類型short 所佔bit數:16
short的包裝器類型爲:java.lang.Short
最小值:-32768
最大值:32767
-------------------------------------------
基本數據類型int 所佔bit數:32
int的包裝器類型爲:java.lang.Integer
最小值:-2147483648
最大值:2147483647
-------------------------------------------
基本數據類型long 所佔bit數:64
long的包裝器類型爲:java.lang.Long
最小值:-9223372036854775808
最大值:9223372036854775807
-------------------------------------------
基本數據類型float 所佔bit數:32
float的包裝器類型爲:java.lang.Float
最小值:1.4E-45
最大值:3.4028235E38
-------------------------------------------
基本數據類型double 所佔bit數:64
double的包裝器類型爲:java.lang.Double
最小值:4.9E-324
最大值:1.7976931348623157E308
-------------------------------------------
基本數據類型char 所佔bit數:16
char的包裝器類型爲:java.lang.Character
最小值:0
最大值:65535

數值在不同進制下的表示

Java支持二進制,八進制,十進制,十六進制的數值表示,我們可以以如下方式定義一個整形數值:

//二進制,以0b或0B開頭
int binary = 0b100;
//八進制,以0開頭
int octal = 0100;
//十進制,無特殊寫法
int decimal = 100;
//十六進制,以0x或0X開頭
int hex = 0x100;
System.out.println("二進制下100的十進制表示:" + binary);
System.out.println("八進制下100的十進制表示:" + octal);
System.out.println("十進制下100的十進制表示:" + decimal);
System.out.println("十六進制下100的十進制表示:" + hex);

以上代碼編譯輸出結果:

二進制下100的十進制表示:4
八進制下100的十進制表示:64
十進制下100的十進制表示:100
十六進制下100的十進制表示:256

類型轉換

假如需要將一個long類型數據轉化爲int,或將byte類型數據轉爲int。就需要類型轉換,類型轉換分爲自動類型轉換強制類型轉換兩種。

1. 自動類型轉換

將佔內存空間小的類型轉換爲佔內存空間大的類型時,不存在轉換風險,java會替我們完成自動類型轉換。示例:

int a = 1;
long b = a;

以上代碼可以編譯通過,因爲int爲4字節而long爲8字節。如果顛倒順序編譯器將不會通過編譯,示例:

long a = 1;
int b = a; //無法通過編譯

2. 強制類型轉換

既然java不會自動將長類型轉化爲短類型,我們有沒有辦法強行轉爲短類型呢?答案是有的。可以使用如下寫法:

long a = 1;
int b = (int)a; //編譯通過

3. 爲什麼java不自動轉化所有類型?

因爲將長類型轉化爲短類型有潛在風險,如果不小心將一個int a = 10000賦值給byte b而編譯器又放行的話,這將很有可能帶來嚴重問題。而java還是賦予了程序員顯式轉換的能力,但是在強制轉換前一定要清楚地瞭解轉換的風險。

靈魂拷問:將int a = 10000賦值給byte b = (byte) a,那麼b是多少?

我們知道強制類型轉換的潛在風險是精度丟失,那麼究竟丟失了多少呢?我們來分析一下
a爲int類型佔4字節,在內存中表示如下:
00000000 00000000 00100111 00010000
而byte爲1個字節,java類型強制轉換實際上是丟棄多餘的bit,可以理解爲截斷超過需要被賦值的類型的長度。現在很容易得到byte b在內存中表示如下:
00010000
以十進制表示,b的值爲16。我們來執行一下以上代碼:

public static void main(String[] args) {
    int a = 10000;
    byte b = (byte) a;
    System.out.println(b);
}

編譯運行輸出結果:16
與我們預料的沒差,驗證了我們前面的猜測。

總結

這節課我們學習了java基本數據類型的相關知識,着手多練習有助於快速提高哦,下一節我們將學習變量類型。

目錄

老王的JAVA基礎課:序言
老王的JAVA基礎課:第1課 計算機基礎知識
老王的JAVA基礎課:第2課 JDK安裝和環境變量配置
老王的JAVA基礎課:第3課 IDEA的安裝和使用
老王的JAVA基礎課:第4課 以hello world學習基礎語法
老王的JAVA基礎課:第5課 面向對象

其他文章

2020年高效搬磚必備的IDEA插件(附安裝包)
詳解從p12證書提取RSA公私鑰和序列號(小白向)

本教程同時發佈在我的公衆號:Java學步園,歡迎加入JAVA初級交流羣:757443185,滑到最上面左側掃描二維碼哦~

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