2010-10-22 94 views
2

考慮:類型轉換在繼承

class TestA { 
    public void start() { System.out.println(」TestA」); } 
} 
public class TestB extends TestA { 
    public void start() { System.out.println(」TestB」); } 
    public static void main(String[] args) { 
     ((TestA)new TestB()).start(); 
    } 
} 

結果是什麼?

A.種皮

B. TESTB

C.編譯失敗。

D.運行時拋出異常。

我給了這個問題的答案是B

是什麼類型轉換的優點是,在第7行做,因爲我們知道方法被調用取決於實際的對象type.can請人給類型轉換開始的例子???????

+0

它只是在那裏混淆你(並花費不必要的機器週期)。 – 2014-08-29 02:22:54

回答

7

這裏沒有「優勢」:它看起來像是引入了一個測試人員對OOP概念和繼承的知識,尤其是你已經回答的知識,即要調用的方法取決於實際的子類型一個東西。

0

類型轉換在重載時發揮作用。 java中的方法重載是在編譯時完成的,並在運行時重寫。

public class Overloading { 
static class A { 
    public void start(){ 
     System.out.println("Overloading$A.start"); 
    } 
} 

static class B extends A { 
    @Override 
    public void start() { 
     System.out.println("Overloading$B.start"); 
    } 
} 


private static void test(A a) { 
    System.out.println("A"); 
} 

private static void test(B b) { 
    System.out.println("B"); 
} 

public static void main(String[] args) { 
    A b = new B(); 
    b.start(); 
    test(b); 
} 

}

PS:不是測試(B),你可以使用測試((A),B)如果B參考是B型的

1

這將打印TESTB。

這就是爲什麼:

首先,我們使用它創建自己的start()方法的種皮類。 然後,我們創建一個TestB,它擴展了TestA(TestB是TestA的一個subversion(「child」)),它覆蓋了他父節點的start()方法。

每個TestB對象也是TestA的一個實例,但反之亦然。所以當我們創建TestA obj = (TestA)new TestB()時,obj將無法​​使用特定於TestB的方法,但它仍然會使用Overrided TestB方法代替本機TestA。

就是這樣。

這裏的類型轉換進場:

你可以使用((TestB)obj).testBMethod(...),調用TESTB特定的方法。更好地利用這將是:

if(obj instanceof TestB) 
{ 
    ((TestB)obj).testBMethod(...); 
} 
+1

不投票也不投票......但它是格式(或缺少它),而不是使用的語言是問題。 – TofuBeer 2010-10-22 05:55:27

+0

感謝您的編輯。我是一個新手。 – 2010-10-22 05:59:16

+0

好的英語也不是我的母語。從我身邊也...... – 2010-10-22 06:06:59

3

重寫代碼,使其更接近,和鑄造刪除:

class TestA 
{ 
    public void start() 
    { 
     System.out.println("TestA"); 
    } 
} 

class TestB 
    extends TestA 
{ 
    public void start() 
    { 
     System.out.println("TestB"); 
    } 
} 

public class Main 
{ 
    public static void main(String[] args) 
    { 
     TestA a; 
     TestB b; 

     a = new TestA(); 
     a.start(); // TestA 

     a = new TestB(); 
     a.start(); // TestB 

     b = new TestB(); 
     b.start(); // TestB 
    } 
} 

把在這裏的石膏會給你這樣的:

public static void main(String[] args) 
{ 
    TestA a; 
    TestB b; 

    a = new TestA(); 
    ((TestA)a).start(); // TestA 

    a = new TestB(); 
    ((TestA)a).start(); // TestB 

    b = new TestB(); 
    ((TestA)b).start(); // TestB 
} 

強制轉換不會改變運行時行爲。它們僅在編譯時有用。

0

在一個稍微不相關的說明中,在C++中查找對象切片[http://stackoverflow.com/questions/580375/how-to-generate-a-compiler-warning-error-when-object-sliced]。在運行時處理方法覆蓋的JAVA動態調度過程中,這是無法完成的。但是,在諸如C++之類的語言中,由於對象切片可能是可能的。

0

請注意,要調用的方法取決於實際的對象類型,而不是返回類型。這裏new TestB()創建TestB的對象,並且這個對象是返回類型TestA。但對象仍然是TestB。

在這裏,您已經重寫了子類中的start()方法,即超類和子類start()方法具有相同的簽名(名稱,參數列表)。然後你已經實例化了一個子類的對象,並將其類型轉換爲超類類型。然後使用類型轉換引用變量(現在是超類類型),您已調用start()方法。 在這種情況下,引用變量指向的對象(在本例中爲子類對象)而不是引用變量的類型,該引用變量決定調用哪個版本的start()。因此,調用了子類start()。如果你想調用超類的start()方法,你應該實例化一個超類對象並用它來調用start()方法。