class Person { void f() {} }
class Student extends Person { void f() {} }
後期綁定/鑄造所以,當我執行下面的代碼:困惑在Java中
Person p = new Student();
((Person) p).f();
爲什麼f()
功能在學生上課的時候變量被投作爲一個人叫什麼名字?我明白爲什麼f()
函數被調用時,它只是p.f()
,但我想我只是困惑什麼演員做。
class Person { void f() {} }
class Student extends Person { void f() {} }
後期綁定/鑄造所以,當我執行下面的代碼:困惑在Java中
Person p = new Student();
((Person) p).f();
爲什麼f()
功能在學生上課的時候變量被投作爲一個人叫什麼名字?我明白爲什麼f()
函數被調用時,它只是p.f()
,但我想我只是困惑什麼演員做。
這是Object Oriented:Polymorphism的基石之一。你有各種各樣的Person實體,每個實體都以自己的方式做f()。它是該對象的實際實例,而不是f()的那個實例。
你總是可以將子類型轉換爲類型這種轉換總是允許在java中,但是因爲實例是子類型的子類型方法將被執行。
您可以瞭解更多信息 檢查Here在Java中,有兩種類型的引用變量鑄造:
是的,您需要直接或間接地實現接口,以便將類對象引用分配給接口類型。
當調用方法時,由於ploymorphsim,它將始終在對象類型上執行,而不是引用類型。
這裏的上傳無關緊要。重寫的方法將始終被調用(如果存在)。
同樣的方法 - 學生中的 - 將被調用,無論您是否將學生轉換爲人員。
上傳一個引用(從子類到超類)不提供真正的功能(實際上通常在內部是無操作的)。另一方面,向下轉換會告訴JVM,您相信超類是指定的子類,如果不是轉換錯誤將會引發。 (我會給出gefei的信用來指出上面的遺漏:演員ALSO告訴編譯器類型,並且編譯器使用這些信息來知道對象(假設)有什麼方法和字段。這並不是嚴格的編譯一個Java程序到字節碼,但它確實允許編譯器執行通常的編譯時間有效性檢查。)
@gefei(閱讀ClassCastException [這裏](http://docs.oracle.com/javase/1.5.0/docs/api/)的描述。) –
但是,你的downvote的主題是你聲稱JVM確實看不到演員。它的確如此。 –
好吧,你是對的,當向下轉換爲一個不是對象或其祖先的真實類型的類時,那麼jvm會拋出一個異常。我只是在約束的背景下思考。 – gefei
在您的示例中的演員完全沒用。編譯器知道p
的類型是Person
。更有趣的將是一個狹窄投:
Person p = getPerson();
if (p instanceof Student) {
Student s = (Student) p;
// do something Student-specific with s
}
在Java中鑄造引用類型不不改變物體的性質;它只告訴編譯器可以對該對象做出什麼假設。在運行時,對象的實際類型用於確定調用的方法。 (請注意,原始類型不適用;將int
轉換爲byte
將更改數據。)
試試這對線(來自ClassCastException的描述):Object x = new Integer(0); System.out.println((String)x);' –
好的。我認爲鑄造一個物體會改變物體的類型而不是參考。不過,我明白向下轉換和向上轉換。謝謝您的幫助。 – sbl03
投射對象對對象本身或對對象的引用都沒有影響。它所做的是通知Java驗證者關於爲對象假設的新類型。但是這個假設只有在通過檢查適當的超類 - 子類關係來驗證投射本身之後纔有效。這可以在驗證時完成(實際上是在加載類時),或者可以在單個對象上動態完成。 –