继承中的类型转换

时间:2010-10-22 05:20:31

标签: java

假设:

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();
    }
}

结果是什么?

  

一个。种皮

     

B中。 TESTB

     

℃。编译失败。

     

d。在运行时抛出异常。

我对这个问题的回答是B

在第7行完成类型转换的优点是因为我们知道要调用的方法取决于实际的对象类型。任何人都可以举例说明类型转换发挥作用??????? / p>

6 个答案:

答案 0 :(得分:7)

这里没有“优势”:它似乎是为了测试一个人对OOP概念和继承的知识而引入的,特别是你已经回答过的知识,即要调用的方法取决于一个实际的子类型。对象

答案 1 :(得分: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
}

强制转换不会改变运行时行为。它们仅在编译时有用。

答案 2 :(得分:1)

它会打印一个TestB。

这就是原因:

首先,我们使用它自己的start()方法创建一个TestA类。 然后,我们创建一个TestB,它扩展了TestA(TestB是TestA的subversion(“child”)),它覆盖了父亲的方法start()。

每个TestB对象也是TestA的一个实例,但反之亦然。因此,当我们创建TestA obj = (TestA)new TestB()时,obj将无法使用特定于TestB的方法,但它仍将使用重写的TestB方法而不是本机TestA。

就是这样。

这里的类型转换发挥作用:

您可以使用((TestB)obj).testBMethod(...)来调用特定于TestB的方法。更好地利用这一点将是:

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

答案 3 :(得分:0)

Typecasting在超载期间发挥作用。 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引用是B类,则可以使用test((A)b)而不是test(b)。

答案 4 :(得分:0)

稍微不相关的说明,在C ++中查找对象切片[http://stackoverflow.com/questions/580375/how-to-generate-a-compiler-warning-error-when-object-sliced]。在JAVA动态调度过程中,它在运行时处理方法覆盖,这是无法完成的。但是,在诸如C ++之类的语言中,由于对象切片,这是可能的。

答案 5 :(得分:0)

请注意,要调用的方法取决于实际的对象类型,而不是返回类型。这里new TestB()创建TestB的对象,该对象是返回类型TestA。但目标仍然是TestB。

这里你重写了子类中的start()方法,即超类和子类start()方法具有相同的签名(名称,参数列表)。然后,您已实例化子类的对象,并将其类型转换为超类类型。然后使用类型转换引用变量(现在是超类类型),您已经调用了start()方法。 在这种情况下,引用变量指向的对象(在本例中是子类对象)而不是引用变量的类型,该引用变量决定调用start()的哪个版本。因此,正在调用子类start()。如果要调用超类start()方法,则可以实例化超类对象并使用它来调用start()方法。