铸造有什么保护作用?

时间:2017-01-09 18:22:46

标签: java casting compiler-errors

此代码中必须转换为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;
    }
}

我们可以写一个简单的例子,我看到并理解,如果我不投,会有麻烦吗?我可以认为运行时可以帮助自己而不会在上面的代码中进行转换,但我当然还没有理解为什么必须进行转换的深层细节。

2 个答案:

答案 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... } 块中,我们有理由相信iff实例,即使java编译器无法确定。 (在这个例子中,它似乎微不足道,但可能有数千行和多个堆栈帧分隔Bar条件和转换。因此,我们可以放心地进行演员表。

但是,如果您对此错了,那么演员阵容实际上是无效的,那么您将在尝试演员阵容的行上获得if。这使问题更加清晰:不是在有问题的实例没有所需功能的随机行上获得异常,而是在尝试转换的地方发生。