本作品採用知識共用署名-非商業性使用-相同方式共用 2.5 中國大陸許可協議進行許可。
無論在C/C++還是在Java,強制類型轉換已經不是陌生的概念了。但是要想全面掌握Java中類型轉換的要點可不那麼簡單,本文將帶領大家一同瞭解有關Java類型轉換的所有要點。
數實值型別的類型轉換
眾所周知,Java有兩種資料類型:基礎資料型別 (Elementary Data Type)與引用資料類型;Java又有兩種基本的類型轉換原則:拓寬轉換原則(widening conversion)與縮小轉換原則(narrowing conversion)。
拓寬轉換與縮小轉換隻適用於基礎資料型別 (Elementary Data Type)中的數實值型別。資料實值型別按照範圍從小到大排列為:
byte short int long float double
當目標類型的範圍比源類型的範圍大時遵循拓寬轉換原則,不必強制轉換。如:
byte b = 10;<br />short s = b;
反之則遵循縮小轉換原則,即
當目標類型的範圍比源類型的範圍小時遵循縮小轉換原則,必須強制轉換。如:
short s = 10;<br />byte b = (byte)s;
需要注意的是拓寬轉換原則不遺失資料。如:
long l1 = Long.MAX_VALUE;<br />float f = l1;<br />long l2 = (long)f;<br />System.out.println("轉換前:" + l1);<br />System.out.println("轉換後:" + l2);
上例輸出結果為:
轉換前:9223372036854775807
轉換後:9223372036854775807
縮小轉換原則在超出目標類型的取值範圍時會導致資料丟失。如:
int i1 = 257;<br />byte b = (byte)i1;<br />int i2 = b;<br />System.out.println("轉換前:" + i1);<br />System.out.println("轉換後:" + i2);
上例輸出結果為:
轉換前:257
轉換後:1
字元類型與數實值型別之間的轉換
基礎資料型別 (Elementary Data Type)char等同於一個無符號短整型,範圍從0x0000到0xFFFF。
從其它數實值型別轉換到char類型時,必須進行強制轉換。如:
byte b = 10;<br />short s = 10;<br />int i = 10;<br />long l = 10L;<br />float f = 10.0F;<br />double d = 10.0;</p><p>char c = (char)b;<br />c = (char)s;<br />c = (char)i;<br />c = (char)l;<br />c = (char)f;<br />c = (char)d;
將char類型轉換成其它數實值型別時,除byte、short必須強制轉換外,int long float double均不必強制轉換。如:
char c = 'a';<br />byte b = (byte)c;<br />short s = (byte)c;<br />int i = c;<br />long l = c;<br />float f = c;<br />double d = c;
參考型別的類型轉換
參考型別的賦值常見於具有繼承關係的兩種類型的轉換。如下面的例子:
public class Person {<br /> public void sleep() {<br /> }<br />}<br />public class Student extends Person {<br /> public void study() {<br /> }<br />}<br />public class Teacher extends Person {<br /> public void teach() {<br /> }<br />}
當目標類型與源類型存在父子關係時,不必強制轉換。如:
Person person = new Student();<br />person.sleep();
上例是一個典型的多態。但如果要從父類引用轉換成子類引用,即
當源類型與目標類型存在父子關係時,必須進行強制轉換。如:
Person person = new Student();<br />person.sleep();<br />if (person instanceof Student) {<br /> Student student = (Student)person;<br /> student.study();<br />}
當然,如果子類引用指向的是一個父類對象,轉換時會拋出ClassCastException異常。如:
Person person = new Person();<br />person.sleep();<br />Student student = (Student) person; // 運行時拋出異常<br />student.study();
進一步,如果要從一個參考型別轉換成不相關的另一個參考型別,即
當源類型與目標類型不存在父子關係時,轉換無法進行,編譯時間會出現錯誤。如:
Teacher person = new Teacher();<br />person.sleep();<br />Student student = (Student) person; // 編譯時間報告錯誤<br />student.study();
數實值型別與封裝類之間的轉換
JDK1.5之後引入了自動裝箱的概念。也就是說
將一個基礎資料型別 (Elementary Data Type)轉換到對應的參考型別時,不必強制轉換。如:
int i = 10;<br />Integer iObj = i;
反之亦然。即
將一個基礎資料型別 (Elementary Data Type)的參考型別轉換到基礎資料型別 (Elementary Data Type)時,不必強制轉換。如:
Integer iObj = new Integer(10);<br />int i = iObj;
運算式中的型別提升原則
在算術運算和位元運算中,數實值型別的資料按以下原則進行型別提升:
byte、short和char型自動轉成int型;如:
byte b1 = 10;<br />byte b2 = 20;<br />int value = b1 + b2;
如果有一個運算元是long型,則整個運算式的結果用long型表示;如:
int i = 10;<br />long l = 20;<br />long value = i + l;
位元運算不能操作float及double類型,因此在算術運算中
如果有一個運算元是float型,則整個運算式的結果用float型表示;如:
long l = 10;<br />float f = 20.0F;<br />float value = l + f;
如果有一個運算元是double型,則整個運算式的結果用double型表示。如:
float f = 10.0F;<br />double d = 20.0;<br />double value = f + d;
特殊的型別提升
Java運算式中有一種特殊的運算式,? 運算式。? 運算式是一個特殊的賦值運算式,它會按照算術運算中的型別提升原則將 : 兩端的運算元提升至統一的類型。如:
byte b = 10;<br />short s = 20;<br />int i = (b == 10) ? b : s;
需要指出的是
如果 : 兩端有一個運算元是參考型別,則整個運算式的結果用Object型表示。
int i = 10;<br />String str = "Hello";<br />Object obj = (i == 10) ? i : str; // 在這裡變數i進行了自動裝箱操作