2017-07-03 63 views
0

我以爲你不能將Parent轉換爲Child,並且只能將Child轉換爲Parent。或者至少如果你這樣做,你將不被允許訪問孩子的功能。將父母給予孩子 - 數組中的奇怪行爲

然後我看到,Java將允許我明確投父到子:

a=(B)a; 

,但不會允許

bArray[0]=a 

a.testB(); 

然而,這是確定的:

bArray[1]=(B)a; 

所以是這樣的:

bArray[1].testB(); 

可有人請解釋一下是怎麼回事!?如何給父類授予一個子類的功能?爲什麼第一次嘗試將數組放入陣列不起作用,但第二次嘗試呢?它不應該一樣嗎?

class A { 
    public void testA() { 
    } 
} 

class B extends A { 
    public void testB() { 
    } 
} 

public class polymorphicObjects { 
    public static void main(String[] args) { 
     B bArray[] = new B[5];  
     A a = new A(); 
     A ab = new B(); 

     a = (B)a; //didnt think you could do this 
     bArray[0] = a; //but if I can the why doesnt this work? 
     a.testB(); //or this 
     bArray[1] =(B)a; //but this does work 
     bArray[1].testB(); //and so does this!? 
    } 
} 
+3

** //爲什麼不工作?** - 因爲您聲明'a'是A型的,所以不要緊。 'A a =(B)new A();'。變量'a'仍然是'A'類型,因爲那是你如何定義它的。無論如何。我確定其實這些都不起作用,如果你嘗試運行它,你只會得到一個ClassCastException。僅僅因爲它編譯不會意味着它有效。 –

+0

哈是類演員異常。我正在爲OCJA學習,他們一直在向我拋出奇怪的東西。沒想到打編譯。謝謝你,先生。 – Mason

回答

0

是否運行bArray[1].testB();實際工作?至少應該拋出一個ClassCastException。在testB()方法內部添加一個打印語句應該有幫助。

所以在這裏,你說a = (B)a;這是非常明確地鑄造一個類型B,但它實際上並沒有任何意義。

考慮到這一點,在第一行bArray[0] = a;中不起作用,因爲它不再被明確強制轉換,所以編譯器會抱怨說您提供的類型不匹配。

在隨後的行bArray[1] = (B)a;中,您明確地告訴編譯器A是B類型的,因此它不會對您發出警告......儘管對方法testB()的調用在運行時會失敗。

+0

你是正確的演員例外。我沒想過要編譯它。我一直在爲OCJA學習,現在只是依靠Eclipse來告訴我紅線。猜猜在編譯之前它無法捕捉到所有的東西。謝謝! – Mason

+0

如果你不介意的話,如果你接受我的回答,我會很感激的:)我只是剛剛開始回報我在大學生涯中依賴的社區。 – SaxyPandaBear

+0

我做過了,但是我沒有足夠的Java Stackoverflow聲望來進行計數:/。我主要只是一個潛伏者哈哈。當我有足夠的代表時,我會再次投票! – Mason

0

在Java中,鑄造具有非常具體的含義(與C語言不同,例如)。你必須區分你的對象實際擁有什麼類,以及編譯器對某些表達式的類是怎麼想的。

鑄造不會改變實際的對象類,但只會改變編譯器對錶達式類的看法。

讓我們通過代碼:

new A()總會給你一個類的對象,編譯器知道。

您存儲到參考變量a,聲明爲類A的,所以從聲明(不是new A()表達)編譯器知道變量a具有A類(允許亞類)。

隨着投式(B) a你不改變任何東西 - 這就是存儲在a對象,只是斷言的編譯器,您作爲開發商,知道存儲在a的對象是B型的(這是不真的,在你的情況下,這是一個A,而不是B)。編譯器不夠聰明,所以他把表達式(B) a視爲有效的並且是B類。他允許你從A轉換到B,因爲B是A的子類,所以A類的變量可能非常好包含B類的對象(例如A a = new B();將完全可以)。在運行時,JVM將檢查實際的對象類並提出ClassCastException,因爲它發現它不是來自子類B的A。

With a = (B) a;將同一個對象存儲回它來自的同一個變量。

你問bArray[0] = a;這不,因爲編譯器編譯,a包含A類的一個對象,數組需要B. bArray[1] = (B) a;將編譯,但拋出ClassCastException只要變量仍然包含運行時與A類相同的對象。

bArray[1].testB();編譯因爲編譯器知道在bArray所有元素都是B類,而B類有這個方法。由於試圖將不屬於B類的對象存儲到bArray中(在編譯時bArray[0] = a;或運行時bArray[1] = (B) a;)將不起作用,因此調用testB()方法是安全的。

+0

這是一個很好的解釋。謝謝。當我有足夠的聲譽來處理問題時,我會回來爲這個答案投票。 – Mason