抛出异常错误

时间:2016-09-23 11:03:55

标签: java oop casting

我决定从Android app:

模拟这个示例代码

TextView txt = (TextView) findViewById(R.id.activity_display_message);

findViewById返回View个对象,然后我们将其转换为TextView一个(TextViewView的子类)

似乎我误解了它的运作方式。我希望此代码能够正常运行,因为C extends B因此我应该将B对象转发给C

但是我在运行时遇到异常,我无法将B强制转换为C

那么有人可以解释我错在哪里吗?为什么Android样本有效?

public class A{
    public static void main(String[] args){
        B b = new B();
        b.f();
        C c = (C)b;
    }
}

class B{
    public void f(){
        System.out.println("Class B");
    }
}

class C extends B{
    public void f(){
        System.out.println("Class C");
    }
}

3 个答案:

答案 0 :(得分:2)

使用Cast操作可以更改对象的静态类型,这是另一种说法"告诉编译器您对正在投射的对象类型的了解。"

如果您的类型为B的变量包含C类型的对象,则可以将该变量强制转换为C

B b = new C();
C c = (C)b; // works fine

这是正确的,因为b的对象实际上是C

b引用的对象 a C时,编译器将捕获您的错误,并抛出强制转换异常:

B b = new B();
C c = (C)b; // throws class cast exception

成功与失败之间的区别取决于运行时对象的实际类型。有效的代码可以将View转换为TextView,因为静态类型为View的变量实际上在运行时引用了TextView

答案 1 :(得分:2)

在java中,如果没有superclass reference variable的演员,则无法将subclass reference variable分配给subclass type。示例可以找到何时需要显式对象引用转换?当您明确地将超类引用转换为子类引用时,编译器很高兴,但编译器并不关心引用所持有的实际对象是什么。它实际上是否有一个超类对象,或者只是一个包含子类对象的超类引用?编译时没有回答,但它必须回答这个问题。

你不能只是拿一个父对象然后突然变成一个孩子。父对象不是子类的实例。如果引用所持有的实际对象是超类对象,则将其转换为子类引用会导致编译时错误。

根据您的情况B is parent classC is its child

class SuperClass {
  // ...
}

class SubClass extends SuperClass {
  // ...
}

public class Program {

  public static void main(String[] args) {

    // case 1: actual SuperClass object

    SuperClass p1 = new SuperClass();

    // case 2: SubClass object is referred by a SuperClass reference 

    SuperClass p2 = new SubClass();

    SubClass s1 = (SubClass) p1; //run time error
    SubClass s2 = (SubClass) p2; //OK
  }

}

答案 2 :(得分:1)

在Android findViewById中返回View类的实例。这是TextView和其他视图元素的直接超类。 所以,如果你想复制类似的东西,那么你可以这样做:

class Test {

    public static void main(String args[]) {

        A a = new A();
        C c = (C)a.getViewByid('c');

        c.f();
    }

}

class A {

    public B getViewByid(char c) {

        B b = null;
        switch (c) {

        case 'b':
            b = new B();
            break;

        case 'c':
            b = new C();
            break;

        default:
            b = new B();
        }

        return b;
    }
}

class B {
    public void f() {
        System.out.println("Class B");
    }

}

class C extends B {
    public void f() {    
        System.out.println("Class C");
    }

}