2010-10-22 163 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()方法。