2016-02-18 80 views
2

我正在研究在Java中進行鑄造,特別是使用接口進行鑄造。假設我有一個接口I,限定了方法跳躍,即:Java編譯器和接口鑄造

interface I{ 
    public void jump(); 
} 

另外假設我有其他3類,ABCA器具IB不。然而,C延伸B並實施I

class A implements I { 
    public void jump(){ 
     System.out.print("A is jumping"); 
    } 
} 
class B { } 
class C extends B implements I { 
    public void jump(){ 
     System.out.print("C is jumping"); 
    } 
} 

現在,如果我嘗試A類型的對象分配給I,是沒有問題的,我甚至不需要鑄造。 I.e .:

I i = new A(); 

好的不需要施放。

據推測,這是因爲編譯器知道另外一實現,如果我嘗試這樣的:

A mya = new A(); 
I i = mya; 

沒有問題,即使mya可以參考的A一個子類。但是AFAIK沒問題,因爲編譯器知道A的每個子類都必須隱式實現jump方法,因此也就是接口A

但是,如果我嘗試將B類型的對象分配給I,那麼我確實需要進行強制轉換。例如

B myb = new B(); 
I i = (I)myb; 

據推測,這是因爲編譯器知道B沒有實現I。但是,因爲B可能指的是執行I的子類,則您可以投射到I。到現在爲止還挺好。 現在這是我的問題:如果我想將類型B的對象指向C(實現I)到I然後我們需要一個強制轉換。這是爲什麼?例如。

B b = new C(); 
I myI = b; //Won't compile this needs a cast 
I myI = (C)b; // This will compile 
myI = (I)b; // This will also compile 

爲什麼不編譯器明白B是指一個C實現嗎?

大概是這樣做的,B可能指的是B這實際上並沒有實現I但爲什麼編譯器不知道這一點?據推測,編譯器僅限於每行僅有的信息?它不能貫穿你的程序,看到b實際上指向了C?如果這是正確的,那麼有人可以指引我參考一些關於Java編譯器如何工作的文獻以及他們的限制是什麼?

回答

5

大概這是因爲編譯器知道B沒有實現I,但是因爲B可以引用一個實現了I的子類,那麼你可以投給我。

不完全是。不管你想要什麼,編譯器都會讓你投B。這並不意味着您在運行時不會得到ClassCastException。 (你的代碼這次可以工作,但是編譯器不會阻止你製造不好的強制轉換。)

爲什麼編譯器不明白B指的是實現I的C?據推測,這與B可以引用B實際上並沒有實現I的事實有關,但爲什麼編譯器不知道這一點。

因爲你告訴它來治療對象爲B當你宣佈B b = new C();

想必編譯器被限制爲僅適用於每一行的信息?它不能運行你的程序,看到b實際上指向一個c?

它可以訪問其餘的代碼。它只是按照你要求的做法:將b作爲B類的對象。

+0

加一個「告訴它治療」 –

-1

在這種特殊情況下,編譯器能夠確定b實際上是指C的一個對象。但是語言創建者選擇不使編譯器如此聰明。

在實際情況下,b指的實際對象不會如此本地化,因此編譯時間可以確定。所以選擇它不會讓編譯器過度靈活,不能解決實際情況。

+0

爲什麼downvote請? – mks