2012-09-06 144 views
0
class Person { void f() {} } 
class Student extends Person { void f() {} } 

後期綁定/鑄造所以,當我執行下面的代碼:困惑在Java中

Person p = new Student(); 
((Person) p).f(); 

爲什麼f()功能在學生上課的時候變量被投作爲一個人叫什麼名字?我明白爲什麼f()函數被調用時,它只是p.f(),但我想我只是困惑什麼演員做。

+0

試試這對線(來自ClassCastException的描述):Object x = new Integer(0); System.out.println((String)x);' –

+0

好的。我認爲鑄造一個物體會改變物體的類型而不是參考。不過,我明白向下轉換和向上轉換。謝謝您的幫助。 – sbl03

+1

投射對象對對象本身或對對象的引用都沒有影響。它所做的是通知Java驗證者關於爲對象假設的新類型。但是這個假設只有在通過檢查適當的超類 - 子類關係來驗證投射本身之後纔有效。這可以在驗證時完成(實際上是在加載類時),或者可以在單個對象上動態完成。 –

回答

1

這是Object Oriented:Polymorphism的基石之一。你有各種各樣的Person實體,每個實體都以自己的方式做f()。它是該對象的實際實例,而不是f()的那個實例。

1

你總是可以將子類型轉換爲類型這種轉換總是允許在java中,但是因爲實例是子類型的子類型方法將被執行。

您可以瞭解更多信息 檢查Here在Java中,有兩種類型的引用變量鑄造:

  • 溯造型:如果您有指子類型對象的引用變量,你可以指定它到 子類型的參考變量。您必須進行明確演員才能完成此操作,結果爲 ,您可以使用此新參考 變量訪問子類型的成員。
  • 上傳:您可以顯式或隱式地將引用變量指定給超類型引用變量。這是一種固有的安全操作,因爲該分配限制了新變量的訪問能力。

是的,您需要直接或間接地實現接口,以便將類對象引用分配給接口類型。

1

當調用方法時,由於ploymorphsim,它將始終在對象類型上執行,而不是引用類型。

0

這裏的上傳無關緊要。重寫的方法將始終被調用(如果存在)。

1

同樣的方法 - 學生中的 - 將被調用,無論您是否將學生轉換爲人員。

上傳一個引用(從子類到超類)不提供真正的功能(實際上通常在內部是無操作的)。另一方面,向下轉換會告訴JVM,您相信超類是指定的子類,如果不是轉換錯誤將會引發。 (我會給出gefei的信用來指出上面的遺漏:演員ALSO告訴編譯器類型,並且編譯器使用這些信息來知道對象(假設)有什麼方法和字段。這並不是嚴格的編譯一個Java程序到字節碼,但它確實允許編譯器執行通常的編譯時間有效性檢查。)

+0

@gefei(閱讀ClassCastException [這裏](http://docs.oracle.com/javase/1.5.0/docs/api/)的描述。) –

+0

但是,你的downvote的主題是你聲稱JVM確實看不到演員。它的確如此。 –

+0

好吧,你是對的,當向下轉換爲一個不是對象或其祖先的真實類型的類時,那麼jvm會拋出一個異常。我只是在約束的背景下思考。 – gefei

0

在您的示例中的演員完全沒用。編譯器知道p的類型是Person。更有趣的將是一個狹窄投:

Person p = getPerson(); 
if (p instanceof Student) { 
    Student s = (Student) p; 
    // do something Student-specific with s 
} 

在Java中鑄造引用類型不改變物體的性質;它只告訴編譯器可以對該對象做出什麼假設。在運行時,對象的實際類型用於確定調用的方法。 (請注意,原始類型不適用;將int轉換爲byte將更改數據。)