此代码中必须转换为Bar
。我试图了解它避免了什么问题。如果编译器允许我使用Foo
作为Bar
而不进行强制转换,那么它是否无法使用Bar
可能具有的扩展功能?还是有一些更重要的原因?或者这个例子太难以解释为什么我必须施展?
class Foo { }
class Bar extends Foo { }
public class Main {
public static void main(String[] args) {
Foo f1 = new Bar();
Bar b1 = (Bar) f1;
}
}
我们可以写一个简单的例子,我看到并理解,如果我不投,会有麻烦吗?我可以认为运行时可以帮助自己而不会在上面的代码中进行转换,但我当然还没有理解为什么必须进行转换的深层细节。
答案 0 :(得分:1)
这可以保护您免受错误的施法。如果您想要使用未经过类型化的类,实际上现在是类型为Bar,您在使用其方法时会看到什么?例如,你实际上是f1类型的f1,然后你尝试使类型Bar的b1指向类Foo。您正尝试从Bar调用方法,但没有实现它。你期待什么?编译器也不会知道。在这种情况下,如果您尝试投放错误的课程,您将只获得java.lang.ClassCastException
,我们知道如何保护。
答案 1 :(得分:1)
如果在层次结构中添加另一个类,则转换的必要性会变得更加清晰。请考虑这组类:
class Foo {}
class Bar extends Foo {}
class Baz extends Foo {}
现在,如果您有Foo
类型的引用,则它可能引用Foo
实例,Bar
实例或Baz
实例。请考虑以下代码snippit:
Foo f;
if (Math.random() > 0.5) {
f = new Bar();
} else {
f = new Baz();
}
您不能简单地致电f
Bar
,因为f
可能不是 a {{ 1}},而是Bar
。因此,演员实际上是在说,"我知道这可能会失败,但我有理由相信它不会如此,所以继续尝试吧#34;例如,我们可以执行以下操作:
Baz
在Foo f;
if (Math.random() > 0.5) {
f = new Bar();
} else {
f = new Baz();
}
if (f instanceof Bar) {
Bar b = (Bar) f;
// do stuff with b...
}
块中,我们有理由相信if
是f
实例,即使java编译器无法确定。 (在这个例子中,它似乎微不足道,但可能有数千行和多个堆栈帧分隔Bar
条件和转换。因此,我们可以放心地进行演员表。
但是,如果您对此错了,那么演员阵容实际上是无效的,那么您将在尝试演员阵容的行上获得if
。这使问题更加清晰:不是在有问题的实例没有所需功能的随机行上获得异常,而是在尝试转换的地方发生。