2017-01-09 147 views
-2

在此代碼中需要轉換爲Bar。我試圖瞭解它避免了什麼問題。如果編譯器將讓我用Foo作爲Bar沒有鑄造,豈不是能夠使用Bar可能具有的擴展功能?還是有更重要的原因?或者,這個例子太簡單了,無法解釋爲什麼我必須施放?鑄造有什麼保護措施?

class Foo { } 
class Bar extends Foo { } 

public class Main { 
    public static void main(String[] args) { 
     Foo f1 = new Bar(); 
     Bar b1 = (Bar) f1; 
    } 
} 

我們可以寫一個簡單的例子,我看的明白,如果我不投會有麻煩?我可以認爲運行時可以幫助自己而不用在上面的代碼中投射,但是我當然沒有理解爲什麼我必須執行投射的深刻細節。

+1

最簡單的例子:'1/2'將導致0,除非你施放他們中的一個將翻一番,所以在代碼'2 /(1/2)'你可以,如果你不投得到一個異常。 – Maroun

+2

你應該看看javas [多態](https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html),這是強制你在這種情況下投射的概念。 –

回答

1

這可以保護您免受錯誤鑄造。如果您想要使用非鑄造類,實際上它現在是Bar類型,那麼在使用它的方法時您會看到什麼?例如,您實際上創建了Foo類型的f1,然後嘗試將Bar類型的b1指向Foo類。你正試圖從Bar調用方法,但沒有實現它。你期望什麼?編譯器也不會知道。在這種情況下,如果您嘗試投錯類,您將獲得java.lang.ClassCastException,我們知道如何防範。

1

投的必要性,如果添加另一個類的層次變得更加清晰。考慮這組類來代替:

class Foo {} 
class Bar extends Foo {} 
class Baz extends Foo {} 

現在,如果你有Foo類型的引用,它可以指Foo例如,Bar實例或Baz實例。考慮下面的代碼片段:

Foo f; 
if (Math.random() > 0.5) { 
    f = new Bar(); 
} else { 
    f = new Baz(); 
} 

你不能簡單地調用f一個Bar,因爲它可能的情況是f不是一個Bar,而是Baz。因此,演員基本上會說:「我知道這可能會失敗,但我有理由相信它不會這麼做,並嘗試它」。例如,我們可以做到以下幾點:

Foo f; 
if (Math.random() > 0.5) { 
    f = new Bar(); 
} else { 
    f = new Baz(); 
} 

if (f instanceof Bar) { 
    Bar b = (Bar) f; 
    // do stuff with b... 
} 

if塊,我們有理由相信,fBar例如,儘管Java編譯器不能肯定這一點。 (在這個例子中它看起來微不足道,但可能有成千上萬的行和多個堆棧幀將if條件與演員分開)。因此,我們可以自信地演員。

但是,如果您錯了,演員陣容實際上是無效的,那麼您會在試圖演員陣容中獲得ClassCastException。這使問題更加清楚:不是在所討論的實例沒有所需功能的隨機行上獲取異常,而是發生轉換嘗試的位置。