类型的变量可以存储对类型对象或其子类型的引用,就像在 case 类中一样。A
A
B
因此,可以有如下代码:
A a = new B();
变量是类型,因此它只能访问该类的API,它无法访问在B类中添加的方法,它引用了哪个对象。但有时我们希望能够访问这些方法,因此应该可以以某种方式将引用存储在某个更准确的类型变量中(此处),通过这些变量,我们可以从B类访问这些附加方法。
a
A
a
B
让我们尝试以这种方式实现它:
B b = a;//WRONG!!! "Type mismatch" error
此类代码给出编译时错误。它碰巧将我们从这样的情况中拯救出来:Type mismatch
class B1 extends A
-
class B2 extends A
我们有.A a = new B1();
现在让我们尝试分配 .请记住,编译器不知道变量a
下实际保存的内容,因此它需要生成对所有可能值都是安全的代码。如果编译器不抱怨它也应该允许编译 。因此,为了安全起见,它不让我们这样做。B1 b = a;
B1 b = a;
B2 b = a;
那么我们应该如何从中分配引用?我们需要明确地告诉编译器,我们在这里知道潜在的类型不匹配问题,但是我们确信,保存在 中的引用可以安全地分配到 类型的变量中。我们通过 将值从 转换为类型来执行此操作。a
B1
a
B
a
B
(B)a
B b = (B)a;
但是,让我们回到您问题中的示例
B b1 = (B) new A();
A a1 = (B) new A();
new
运算符返回与创建对象相同类型的引用,因此返回该类型的引用,因此new A()
A
B b1 = (B) new A();
可视作
A tmp = new A();
B b1 = (B) tmp;
这里的问题是,您不能将对超类对象的引用存储在其派生类型的变量中。
为什么存在这样的限制?假设派生类添加了一些超类型没有的新方法
class A {
// some code
}
class B extends A {
private int i;
public void setI(int i){
this.i=i;
}
}
如果允许这样做
B b = (B)new A();
你以后可能会以调用 结束。但它是正确的吗?否,因为类 A 的实例没有该方法使用的方法或字段。b.setI(42);
setI
i
因此,为了防止在运行时出现这种情况,抛出。(B)new A();
java.lang.ClassCastException