Java 原生類型與封裝器類型深度剖析
摘要:
本文對 Java 原生類型與封裝器類型進行深度剖析,主要涉及以下四個方面:原生類型與封裝器類型基礎、字面值概念和種類、 基本類型的自動轉型與強制轉型和自動裝箱與拆箱機制。
要點:
原生類型與封裝器類型
字面值概念和種類
基本類型、自動轉型與強制轉型
自動裝箱與拆箱機制(Autoboxing and Unboxing) 一. 原生類型與封裝器類型
在Java中有八種基礎資料型別 (Elementary Data Type):
特別需要注意以下幾點:
未帶有字元尾碼標識的整數預設為 int 類型,未帶有字元尾碼標識的浮點數預設為 double 類型;
只有 byte,char,short,int 四種基本類型及其封裝類(需要Java5.0/1.5以上版本支援)可以用於 switch 語句(只有 enum 類型 和 int類型可以應用到 swith),其它類型編譯會報錯;
char(兩個位元組)可以用單引號表示單個字元(可以是漢字),如:‘良’,’A’;
整數可以由二進位(以0B/0b開頭)、八進位(以0開頭的整數)、十進位、十六進位(以0x或0X開頭的整數)表示; 二. 字面值
在Java原始碼中,字面值用於表示固定的值(fixed value)。數值型的字面值是最常見的,字串字面值也很常見可以算是一種,當然也可以把特殊的null當做字面值。字面值大體上可以分為 整型字面值(int型字面值 、 long型字面值 和 字元字面值)、整型字面值、浮點型字面值(double型字面值 和 float型字面值)、字串字面值、特殊字面值 四種。
(1) 整型字面值
從形式上看是整數的值歸類為整型字面值。例如: 10, 100000L, ‘B’‘B’、0XFF 這些都可以稱為整型字面值。在使用時,需要注意以下幾點:
整型字面值可以用 十進位、十六進位(以0X/0x開頭)、八進位(以0開頭) 和 二進位(以0B/0b開頭) 來表示。當然,基數不能超出進位的範圍,比如09是不合法的,八進位的基數只能到 7。
一般情況下,字面值建立的是int類型,但是int字面值可以賦值給 byte、short、char、long 和 int。當然,前提是字面值在目標範圍以內(Java會自動完成轉換);如果試圖將超出範圍的字面值賦給某一類型(比如把128賦給byte類型),編譯通不過,需要強制類型轉換。
byte b0 = 128; // Type mismatch: cannot convert from int to bytebyte b1 = 12; // OKbyte b2 = (byte)300;// OK 需要強制轉換,但表示的數字是截取後的數字(300二進位為100101100,截取後為00101100,即44)char c0 = 5; // OKchar c1 = char(-3); // 編譯通過,但列印值為 。(char 為無符號的)System.out.println(c1); // 。
1 2 3 4 5 6 7
如果想建立一個 int 類型無法表示的 long 類型,則需要在字面值最後面加上L或者l(通常建議使用容易區分的L)。所以,整型字面值包括int字面值和long字面值兩種。
Java中,字元字面值用單引號括起來(也屬於整型字面值),如‘@’,‘1’。所有的UTF-16字元集都包含在字元字面值中。不能直接輸入的字元,可以使用逸出字元,如‘\n’為換行字元。也可以使用八進位或者十六進位表示字元,八進位使用反斜線加3位元字表示,例如’\141’表示字母a。十六進位使用\u加上4為十六進位的數表示,如’\u0061’表示字元a。也就是說,通過使用逸出字元,可以表示鍵盤上的有的或者沒有的所有字元。常見的逸出字元序列有:
\ddd(八進位) 、 \uxxxx(十六進位Unicode字元)、\’(單引號)、\”(雙引號)、\ (反斜線)\r(斷行符號符) \n(分行符號) \f(換頁符) \t(定位字元) \b(回格符)
(2) 浮點字面值
浮點字面值簡單的理解可以理解為小數,分為float字面值和double字面值。如果在小數後面加上F或者f,則表示這是個float字面值,如11.8F。如果小數後面不加F/f(如10.4),或者小數後面加上D/d,則表示這是個double字面值。
double d1 = 10; // OK,自動類型轉換double d2 = 11.4; // OKdouble d3 = 1.23E3; // OK double d4 = 10D; // OK double d5 = 0.4D; // OK float f1 = 10; // OK,自動類型轉換float f2 = 11.1F; // OKfloat f3 = 11.1; // Type mismatch: cannot convert from double to float
1 2 3 4 5 6 7 8
(3) 字元及字串字面值
Java中字元字面值用單引號括起來,如‘@’,‘1’。所有的UTF-16字元集都包含在字元字面值中。不能直接輸入的字元,可以使用逸出字元,如‘\n’為換行字元。也可以使用八進位或者十六進位表示字元,八進位使用反斜線加3位元字表示,例如’\141’表示字母a。十六進位使用\u加上4為十六進位的數表示,如’\u0061’表示字元a。也就是說,通過使用逸出字元,可以表示鍵盤上的有的或者沒有的所有字元。常見的逸出字元序列有:
\ddd(八進位) 、 \uxxxx(十六進位Unicode字元)、\’(單引號)、\”(雙引號)、\ (反斜線)\r(斷行符號符) \n(分行符號) \f(換頁符) \t(定位字元) \b(回格符)
字串字面值則使用雙引號,字串字面值中同樣可以包含字元字面值中的逸出字元序列。
(4) 特殊字面值
null 是一種特殊的類型(type),可以將它賦給任何參考型別變數,表示這個變數不引用任何東西。如果一個參考型別變數為null,表示這個變數不可用。
還有一種特殊的 class literal,用 type name 加上 .class 表示,例如 String.class。 首先,String是類Class(java.lang.Class)的一個執行個體(對象),而”This is a string”是類String的一個對象。然後,class literal用於表示類Class的一個對象,比如String.class用於表示類Class的對象String。簡單地說,類字面值(class literal)就是諸如String.class 、Integer.class這樣的字面值,它所表示的就是類String、類Integer。如果輸出Integer.class,你會得到class java.lang.Integer。List.class的輸出為interface java.util.List。總之,class literal 用於表示類型本身。
特別需要注意: 在 在數值型字面值 中可以 中可以使用底線(JDK7開始,可以在數值型字面值(包括整型字面值和浮點字面值)插入一個或者多個底線。但是底線只能用於分隔數字底線只能用於分隔數字,不能分隔字元與字元,也不能分隔字元與數字);
int x = 123_456_789; // 在編譯的時候,底線會自動去掉。float f = 1.22___33__44; //可以連續使用底線int = _123; // Errorlong = 1_L; // Error
1 2 3 4
三. 自動轉型與強制轉型
1、 自動轉型
自動轉型總原則:byte,short,char(同級)-> int -> long -> float -> double (由低精度到高精度)
(1) 由低精度到高精度的自動轉換
具體可分為以下兩種情形: 從位元低的類型向位元高的類型轉換
byte b = 1; char c = 1; short s = 1; int i = 1; c = b; // Error,同級 c = s; // Error,同級 s = c; // Error,同級 i = c; // OK
1 2 3 4 5 6 7 8 9
從整型向浮點型的轉換———-
從整型向浮點型的轉換
int i = 1; long t = 1; float f = 1; double d = 1; f = i; // Ok f = t; // Ok d = f; // Ok
1 2 3 4 5 6 7 8 9
(2) 運算子對基本類型的影響
具體可分為以下兩種情形:
1) 當使用 +、-、*、/、%、==、>、< 等 等運算子對基本類型進行運算時,遵循如下規則:
兩個運算元中,先考慮是否有一個是double類型的。如果有,另一個運算元和結果 將會被轉換成double類型。再依次考慮float,long。除此之外,兩個運算元(包括byte、short、int、char)都將會被轉換成int類型。
byte b1 = 10 ; //OK,會檢查發現10沒有超過byte類型的最大值byte b2 = 12; //OK,會檢查發現12沒有超過byte類型的最大值byte b = b1 + b2; //Error,byte類型在計算時會自動提升為int類型,此時就會報錯,因為b1+b2實際上是int類型,但是左側的變數為byte類型。short s1=1; //OK,會檢查發現1沒有超過short類型的最大值s1=s1+1; //Error,因為s1+1 結果int,但左側變數為 short,報錯s1++; //OK,不會報錯,與s1=s1+1不同。。。,會檢查發現2沒有超過short類型的最大值s1=1+1; //OK,1+1 是個編譯時間可以確定的常量,'+'運算在編譯時間就被執行了,而不是在程式執行的時候,這個語句的效果等同於s1=2
1 2 3 4 5 6 7 8 9 10 11
2) 當使用 +=、-=、*=、/=、%= 、 i++、 ++i 運算子對基本類型進行運算時,遵循如下規則:
運算子右邊的數值將首先被強制轉換成與運算子左邊數值相同的類型,然後再執行運算,且運算結果與運算子左邊數實值型別相同。自增(減)運算也類似。
short s1=1; // OK,會檢查發現1沒有超過short類型的最大值short s2;s1+=1; // OK,正確,1首先被強制轉換為short型,然後再參與運算,並且結果也是short類型s2 = ++s1; // OK,正確,s2的值為2