P55: 如果要執(zhí)行窄化轉(zhuǎn)換(
narrowing conversion)的操作(也就是說(shuō),將能夠容納更多信息的數(shù)據(jù)類(lèi)型轉(zhuǎn)換成無(wú)法容納那么多信息的類(lèi)型),就有可能面臨信息丟失的危險(xiǎn)。此時(shí),編譯器強(qiáng)制要求我們進(jìn)行類(lèi)型轉(zhuǎn)換,這實(shí)際上是說(shuō):“這可能是一件危險(xiǎn)的事情,如果無(wú)論如何都要這么做,必須顯式進(jìn)行類(lèi)型轉(zhuǎn)換?!倍鴮?duì)于擴(kuò)展轉(zhuǎn)換(widening conversion),則不必顯式的進(jìn)行類(lèi)型轉(zhuǎn)換,因?yàn)樾骂?lèi)型肯定能夠容納原來(lái)類(lèi)型的信息,不會(huì)造成任何信息的丟失。
上面這段話(huà)應(yīng)該分成基本數(shù)據(jù)類(lèi)型和引用類(lèi)型兩個(gè)方面進(jìn)行討論。
基本數(shù)據(jù)類(lèi)型
int a = 1;
float b = 91.1f;
//需要進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換,轉(zhuǎn)換后的a的值是91,剩下的0.1則丟失了。
a = (int) b;
//不需要進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換
b = a;
如上述代碼所示,b的類(lèi)型是float,擁有比int更多的內(nèi)容,轉(zhuǎn)成int類(lèi)型會(huì)損失部分?jǐn)?shù)據(jù),所以我們需要使用(int)進(jìn)行強(qiáng)制轉(zhuǎn)換。而從int轉(zhuǎn)成float則不需要進(jìn)行強(qiáng)制轉(zhuǎn)換,因?yàn)檗D(zhuǎn)換過(guò)程中不會(huì)丟失任何數(shù)據(jù)。
引用類(lèi)型
class TestA {
int a = 11;
}
class TestB extends TestA {
int b = 1;
}
class TestC {
int a = 11;
}
public class Test {
public static void main(String[] args) {
//不需要強(qiáng)制類(lèi)型轉(zhuǎn)換
TestA a = new TestB();
//需要強(qiáng)制類(lèi)型轉(zhuǎn)換
TestB b = (TestB) a;
//會(huì)拋出java.lang.ClassCastException
TestB bb = (TestB) new TestA();
}
}
與基本數(shù)據(jù)類(lèi)型不同的是,我們的對(duì)象是存在堆上面的,不管怎么轉(zhuǎn)換,其內(nèi)容都是不變的,改變的只是該對(duì)象所能夠展示的能力,也就是其能夠調(diào)用的方法和變量。
首先TestB是繼承TestA的,TestB對(duì)象就是一個(gè)TestA對(duì)象。這里是和基本數(shù)據(jù)類(lèi)型不一樣的,因?yàn)樗诙焉系膶?duì)象是不會(huì)發(fā)生改變的,也就不存在數(shù)據(jù)的丟失問(wèn)題。所以下面語(yǔ)句不需要強(qiáng)制轉(zhuǎn)換,也不會(huì)報(bào)異常。
TestA a = new TestB();
然后我們想把TestB對(duì)象重新被TestB引用,那就必須使用強(qiáng)制類(lèi)型轉(zhuǎn)換了。
//需要強(qiáng)制類(lèi)型轉(zhuǎn)換
TestB b = (TestB) a;
因?yàn)楝F(xiàn)在編譯器只知道a是一個(gè)TestA對(duì)象,TestA有TestB和TestC兩個(gè)子類(lèi)。編譯器要求強(qiáng)轉(zhuǎn)是提醒我們注意這部分可能出錯(cuò)。如果拋開(kāi)編譯器看的話(huà),不強(qiáng)轉(zhuǎn)運(yùn)行是不會(huì)出錯(cuò)的。
//會(huì)拋出java.lang.ClassCastException
TestB bb = (TestB) new TestA();
現(xiàn)在我們看最后一部分,這行代碼在編譯的時(shí)候是不會(huì)報(bào)錯(cuò)的,因?yàn)?code>TestA與TestB存在繼承關(guān)系,所以編譯能夠通過(guò)。但是在運(yùn)行的時(shí)候,TestA對(duì)象是不能夠轉(zhuǎn)成TestB對(duì)象的,因?yàn)槠湓诙焉鲜遣话l(fā)生變化的,TestB的一些獨(dú)有的變量和方法,TestA對(duì)象是不能夠顯示出來(lái)的。如果我們?cè)谵D(zhuǎn)換的時(shí)候不報(bào)錯(cuò),那么使用bb來(lái)調(diào)用一些TestB獨(dú)有的方法的時(shí)候一樣還是要報(bào)錯(cuò)的。