2016-04-02 59 views
0

在Java中變量賦值期間是否有用途投射?在Java中賦值期間投射

例如,我有兩個班,人員和學生,從人繼承:

  • 人| -id:int
  • 學生 - >人員| -gpa:雙

然後在主我有以下代碼:

Student S = new Student(1, 4.00); 
Person P = (Student)S; 
System.out.println(P.getId() + " " + ((Student)P).getGpa()); 

的IntelliJ告訴我,在P = (Student)S鑄造是多餘的,如果我調用getGpa方法時,只投它的工作原理:

Student S = new Student(1, 4.00); 
Person P = S; 
System.out.println(P.getId() + " " + ((Student)P).getGpa()); 

但是,它給了我一個錯誤,如果我任職期間投下但不是當我再次打電話getGpa:

Student S = new Student(1, 4.00); 
Person P = (Student)S; 
System.out.println(P.getId() + " " + P.getGpa()); 

所以我的問題是 - 是否有一種情況下,在轉讓期間鑄造是有用的?或者它是允許的,但總是多餘的,因爲你仍然必須告訴編譯器每個方法調用你正在轉換爲子類型?

謝謝你的幫助。

+1

是關於在轉換過程中關於轉換的一般問題,還是關於將某些東西轉換爲原來的類型的問題。如果問題是「它是否已經是多餘的東西」,答案是肯定的。 'S'是'Student'類型,所以將它轉換爲'Student'什麼也不做。 'P'的類型是'Parent',所以將它轉換爲'Student'就可以做一些事情。 –

+0

這是多餘的,因爲學生*是-a *人,所以不需要演員。鑄造任務的一種情況是'something =(Something)foo();'。 foo'返回一個Object。 – ChiefTwoPencils

+0

@DavidSchwartz我問的是在對象之間而不是基元之間進行投射 - 所以我認爲你只能基於繼承關係進行向上/向下投射。在這種情況下,我不會投射到相同的類型,我將投射到學生,以便我可以訪問Student中的getGpa方法。所以有一點,但我特別要問,爲什麼甚至允許有人做'P =(Student)S',如果我不得不在調用getGpa方法時再次拋出它。 「 – allstar

回答

2

當您知道編譯器沒有的東西時,在賦值過程中投射並不是多餘的。

當您指定Student對象Person變量,沒有必要投,因爲編譯器知道從PersonStudent繼承。但是如果將Person對象分配給Student變量,編譯器不知道Person對象是否也是Student對象。

在這種情況下,您必須在賦值期間使用cast來告訴編譯器,您知道這個特定的對象也是Student。您通常會首先使用instanceof進行驗證。

if (P instanceof Student) { 
    Student S2 = (Student) P; // here the casting during assignment is required 
    S2.getGpa(); 
} 
+0

這是有道理的,但我有一個如何在實踐中的問題。看起來P是Student實例的唯一原因是你實際上將一個Student對象賦給了一個Person變量。看起來更恰當的做法是將某些事物分配給它們相同的類型,並在不同地使用它時進行投射......爲什麼要做類似'Person P = new Student();'? – allstar

+0

您可能有一個「人員」對象的列表,您想迭代並僅對特定類型的對象執行某些操作。你也可能有一個函數接受一個'Person'對象,但如果它也是'Student',需要做一些特殊的事情。 – kichik

+0

@allstar,「爲什麼要做像P =新學生()的東西;?」因爲你喜歡面向對象和多態的好處。 – ChiefTwoPencils

2

的IntelliJ告訴我,在P = (Student)S鑄造是多餘的

這是絕對正確的。 PersonStudent的基類,所以任何Student自動爲Person

所以我的問題是 - 是否有一種情況下,在轉讓期間鑄造是否有用?

不,它是多餘的,它降低了代碼的可讀性。

即使您必須以統一的方式處理派生對象,例如將它們存儲在基本類型的對象集合中,對基類的轉換仍然毫無用處。當你確信你的A類的對象,事實上,一個子類B的一個對象,你不能表達對程序的知識以任何其他方式

List<Person> list = new ArrayList<>(); 
... 
Student student = new Student(); 
... 
list.add((Person)student); // <<= This is redundant, too. Don't do it. 
0

鑄造是有用的,經常需要。

0

P = (Student)S的情況下,如果S是Student的實例,那麼這樣做沒有好處,因爲編譯器已經知道這一點。

如果您後來有Student Q = P但是這不起作用,您將需要編寫Student Q = (Student)P。演員被要求的原因是不能保證P實際上是一個學生(例如,它可能是一個導師,這也是一個人)。