8種類型概述
- 整型
byte
short
int
long
- 浮點型
float
double
- 布爾型
boolean
- 字符型
char
8種數據類型佔用內存空間
現代計算機通過集成電路的電信號控制開關,只能識別0/1,例如0101000…,
十進制 0 1 2 3
二進制 0 1 10 11
而bit
是計算機可以識別的最小單位,表示二進制的0/1,有如下的換算關係:
1Byte(字節)= 8bit(比特位) = 8位的0/1
1Kb = 1024 Byte
1Mb = 1024 Kb
1Gb = 1024 Mb
1Tb = 1024 Gb
1Pb = 1024 Tb
1Zb = 1024 Pb
-
每種數據類型的存儲空間,具體原理請參見下文
-
若聲明類型時未賦值則8種數據類型的默認值都像0看齊
-
char 默認字符
\u0000
表示空字符(非空格) -
十進制和二進制轉換
- 十進制轉成二進制:
除2取餘,逆序輸出
- 十進制轉成二進制:
2|6 0
2|3 0
2|1 1
2|0 1
12=1100=0*2^0+1*2+1*2^2+1*2^3
- 二進制轉化成十進制
01111111=1*2^0+1*2^1+1*2^3+1*2^4+1*2^5+1*2^6+0*2^7=127
Java中的數字類型,數字都有正負之分,所以在二進制中有一個符號位,在二進制的最左邊,0表示正數,1表示負數。
- 不同數據類型的取值範圍的由來
byte類型爲例,byte佔8個比特位,最大值是0111 1111
,由前面可知換算成十進制是127
byte最小值是-128(和原碼、反碼和補碼有關) - 其他進制
- 十進制 0 1 2 3 4 5 6 7 8 9
- 二進制 0 1 10 11 100…
- 八進制 0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20
- 十六進制 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20
- 處理字符
計算機善於處理計算關係,但現實中的文字和語言十分多樣,計算機無法直接轉化成二進制,需要人爲的制定字符編碼表:
計算機最初只支持英文,例如
‘a’ --97-- 01100001
‘A’ --65
‘0’ --48
‘a’ --按照ASII解碼–> 01100001
01100001 --按照ASII編碼–> ‘a’
當編碼和解碼採用同一種字典/對照表時,不會出現亂碼
當編碼和解碼採用不同一種字典/對照表時,可能會出現亂碼
字典的薄厚(不同的編碼系統)決定了存儲字符對應關係的多少:
- 中文編碼:GBK2312< GBK <GB18030
- 全球編碼unicode
- UTF-8:比較節省空間
- UTF-16
- UTF-32
- Java採用的是unicode編碼,因此標誌符可以使用中文(不建議使用)
字符型
- 字符型包括字符和字符串類型
- 字符通過
''
包裹,字符串通過""
包裹,二者不兼容,Java一個字符包括2個字節,而中文恰好是一個字符佔2個字節,因此可以存儲中文文字,例如char a = 'a'; char b = '帥'
,但是char a = "a"
不行,因爲"a"
是字符串不能賦值到char
類型 - 通過
'\'
轉義,轉義字符也屬於char
類型\n
System.out.print輸出不換行,System.out.println換行\t
製表符\\
\
本身\'
'
本身\"
"
本身\u
\u
表示16進制的unicode編碼\u4e2d
表示漢字“中” 可通過native2ascii命令將字符轉換成16進制
整數型
-
Java語言中的“字面值”被默認當作
int
, 如果想要其變成long
需要在後面加上l/L
(建議L ) -
字面值可以以三種方式開始,但輸出默認爲十進制
- 10進制:常用
- 以0開頭的8進制,010
- 以0x開頭的16進制,0x10
-
類型自動轉換
long x = 888
;//888 int字面值賦值給長整型的x,小容量可以自動轉換成大容量long x = 2147483648
;//右邊的值2147483648默認當作int,本身超出int 4個字節的容量,因此還未賦值給左邊的long型就會導致錯誤(面試題目)long x = 2147483648L
;添加L使得變成long型
-
大容量無法自動轉換成小容量數值,需要通過
(TYPE)
強制轉換,但可能嚴重損失精度
long x = 100L;
//將100變爲長整型並賦值給長整型x
int y = x;
//將長整型賦值給整型,小的存不了大的,轉換失敗,大容量無法自動轉換成小容量
int y = (int) x;
//先強制將長整型x轉換成整型再賦值給整型y,可能會丟失精度 -
大數轉小數的時候爲什麼會損失精度?
這要從大數轉小數的原理出發,例如int x = 100L
強制將8字節的長整型100轉換成4個字節的整型,其過程如下
100L:00000000 00000000 00000000 00000000 00000000 00000000 00000000 01100100
要將其轉換成4個字節的int
,計算機會從前面砍掉4個字節,因此剩下:
00000000 00000000 00000000 01100100
而該值換算後還是100,並未損失精度;
但是int x = 2147483648L
,按照同樣的步驟轉換:
2147483648L:00000000 00000000 00000000 00000000 10000000 00000000 00000000 00000000
,強制轉換爲4個字節的整型即截掉前面4個字節,此時剩下:
10000000 00000000 00000000 00000000
,很明顯這是一個負數,實際上是-2147483648,可見損失精度之大 -
總結來說,若待轉換的數據並未超過轉換之後範圍,是不會損失精度的,但是若超過了轉換之後的範圍,則可能嚴重損失精度
實際上,Java提供了更爲便捷的數據類型自動轉換方式,例如byte x = 56
,按照之前的知識,4個字節的int
是無法自動轉換爲1個字節的byte
的,但是隻要不超過byte的取值範圍-128~127
,該賦值語句完全可以;但是byte x = 128
則不合法,因爲128已經超出了byte
的存儲範圍了
- 更一般的規律是,當整數字面值不超過
byte、short、char
的取值範圍,這個字面值可以直接賦值給byte、short、char
,這是Java追求更爲簡潔的語法
public class DataType{
public static void main(String[] args){
// int x = 100L; //大數轉小數報錯
int x = (int) 100L; //加上(int)將100L強制轉換爲int,不會損失精度
System.out.println(x);
int y = (int) 2147483648L; //2147483648L已經超出待轉換類型的範圍,強制轉換會嚴重損失精度
System.out.println(y);
byte i = 56; //支持byte類型的範圍類大數轉小數
System.out.println(i);
//bytj j = 128; //超出byte類型報錯
byte j = (byte) 128; //強制轉換嚴重損失精度
System.out.println(j);
char k = 32767; //不超過char的取值範圍,編譯通過
char m = (char) 32768; //超過char的取值範圍,直接編譯失敗,強制轉換損失精度
System.out.println(m);
}
}
浮點型
- 浮點型包括
float
和double
,分別佔4個和8個字節,由於計算機內存有限,對於浮點型都是近似接近的。例如1/3=0.3333333333333…是無限循環小數,用有限的計算機內存資源存儲無限的數據只能是近似的 - java對於所有浮點型字面值
1.0
會默認當作double
,不能直接賦值給float
類型,若想變成float
可以通過:- 1.通過
float
強制類型轉換,可能會損失精度 - 2.直接在字面值後加上
F/f
- 1.通過
- 雖然
double
看似精度很高,但是對於財務領域依然不夠(動輒百億/千億的資金若因爲精度損失則會損失巨大),因此在java基礎SE類庫
中,提供了更高精度的java.math.BigDecimal
類庫幫助運算,只不過它們屬於引用的數據類型,不屬於基礎數據類型 類庫
是前人已經編寫好的專門處理某些特定領域問題的java代碼,java強大之處正是因爲可以基於這套龐大類庫開發。我們使用的String[] args
實際上就是使用的String.class
- SE
類庫
的字節碼一般位於類似jdk-version-x/lib/*.jar/*.class
- SE
類庫
的源碼在類似jdk-version-x/src.zip
中的.java
源碼
- SE
布爾型
- 布爾型
boolean
,在java中只有2個值true/false
,不像其他語言可以用1/0
表示,聲明一個布爾型boolean age = true
- 布爾型主要是邏輯運算和條件判斷,例如:
public class Bool{
public static void main(String[] args){
boolean age = false; //聲明一個boolean類型false
if(age){
System.out.println("kids");//條件真則執行
}else{
System.out.println("adults");//條件假執行
}
}
}
類型轉換規則
- 除了
boolean
,其他7種類型之間都可以相互轉換 - 小數類型轉大數類型時是自動轉換,從小到到排序爲:
byte < short/char < int < long < float < double
注意:任何浮點類型都比長整型還大;short
和char
雖然都是2個字節,但是char
可以取更大的正整數 - 大數轉小數的時候需要使用強制轉換符,並且在運行的時候可能會損失精度,需謹慎使用
- 當整數字面值沒有超出
byte/short/char
取值範圍時,可以直接賦值 byte/short/char
混合運算時,先各自轉換成int
再運算- 多種類型運算時先轉換成最大類型再運算
參考
B站動力節點老杜老師的Java教程(原視頻戳這裏)