1. 類型轉換
存儲引用類型(類)的變量也可以轉換為不同的類型。但這僅適用於單一類型層次結構。讓我們看一個簡單的例子。假設我們有以下類層次結構,其中下面的類繼承上面的類。
引用類型和原始類型的類型轉換也被歸類為擴大和縮小。
我們看到 Cat 類繼承了 Pet 類,而 Pet 類又繼承了 Animal 類。
如果我們這樣寫代碼:
Animal kitten = new Cat();
這是一個擴大的類型轉換。它也稱為隱式轉換。我們擴大了cat引用,現在它指向一個Cat對象。通過這樣的類型轉換,我們將無法使用kitten引用來調用Cat類中存在但Animal類中不存在的方法。
縮小轉換(或顯式轉換)發生在相反的方向:
Cat cat = (Cat) kitten;
我們明確指出我們想要將存儲在kitten變量(其類型為Animal )中的引用轉換為Cat類型。
2.檢查對象的類型
但是你在這裡需要非常小心。如果你這樣做:
Animal beast = new Cat();
Wolf grayWolf = (Wolf) beast;
編譯器會允許這段代碼,但是程序運行的時候會出現錯誤!JVM 會拋出一個異常:
Exception in thread "main" java.lang.ClassCastException: Cat cannot be cast to a Wolf
對Cat對象的引用只能存儲在類型為 Cat 類的祖先的變量中:Pet、Animal 或 Object。
這是為什麼?
這裡的相關點是對象引用用於引用該對象的方法和變量。如果我們使用 Animal 變量來存儲對 Cat 對象的引用,就不會有任何問題:Cat 類型始終具有 Animal 類型的變量和方法——它繼承了它們!
但是如果 JVM 允許我們在 Wolf 變量中存儲對 Cat 對象的引用,那麼我們可能會遇到這樣一種情況:我們可能會嘗試使用 grayWolf 變量來調用存儲在該變量中的 Cat 對像中不存在的方法. 這就是為什麼這種安排是不允許的。
Java 有一個特殊的instanceof
運算符,可以讓您檢查對像是否屬於某種類型,因此是否可以存儲到某種類型的變量中。它看起來很簡單:
variable instanceof Type
例子:
Animal beast = new Cat();
if (beast instanceof Wolf)
{
Wolf grayWolf = (Wolf) beast;
}
此代碼不會導致錯誤 — 即使在運行時也是如此。
這裡有一些例子可以說明這種情況:
加寬類型轉換 | 描述 |
---|---|
|
這是一個經典的擴大轉換——不需要類型轉換運算符。 在 |
縮小類型轉換 | |
|
經典收縮轉換:您需要添加類型檢查和強制轉換運算符。 變量 Cow cow 存儲對對象的引用Whale 。 我們驗證是這樣的,然後進行(縮小)類型轉換。或者它也被稱為:
類型轉換
.
|
|
您可以在不檢查對像類型的情況下縮小引用類型。 如果 cow 變量引用的對像不是 a ,則將生成 Whale an 。InvalidClassCastException |
3.調用原始方法:super
關鍵字
當覆蓋父類的方法時,有時我們不想用我們自己的方法替換它,而只是想稍微補充一下。
如果能在我們的方法中調用父類的方法,然後執行一些我們自己的代碼就好了。或者也許先執行我們自己的代碼,然後再調用父類的方法。
而 Java 讓我們做到了這一點。要調用父類的方法,請執行以下操作:
super.method(arguments);
例子:
class PeaceTime
{
public double getPi()
{
return 3.14;
}
}
class WarTime extends PeaceTime
{
public double getPi()
{
return super.getPi()*2; // 3.14*2
}
}
戰時,值Pi
可以大於6!當然,我們是在開玩笑,但這個例子演示了這一切是如何工作的。
這裡有幾個例子來澄清一些事情:
代碼 | 描述 |
---|---|
|
Cow 和Whale 類 |
|
屏幕輸出將是:
|
這是很難的事情。老實說,這是OOP中最難的事情之一。也就是說,您確實需要知道並理解它。
GO TO FULL VERSION