2017-01-09 144 views
-2

在此代码中需要转换为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; 
    } 
} 

我们可以写一个简单的例子,我看的明白,如果我不投会有麻烦?我可以认为运行时可以帮助自己而不用在上面的代码中投射,但是我当然没有理解为什么我必须执行投射的深刻细节。

+1

最简单的例子:'1/2'将导致0,除非你施放他们中的一个将翻一番,所以在代码'2 /(1/2)'你可以,如果你不投得到一个异常。 – Maroun

+2

你应该看看javas [多态](https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html),这是强制你在这种情况下投射的概念。 –

回答

1

这可以保护您免受错误铸造。如果您想要使用非铸造类,实际上它现在是Bar类型,那么在使用它的方法时您会看到什么?例如,您实际上创建了Foo类型的f1,然后尝试将Bar类型的b1指向Foo类。你正试图从Bar调用方法,但没有实现它。你期望什么?编译器也不会知道。在这种情况下,如果您尝试投错类,您将获得java.lang.ClassCastException,我们知道如何防范。

1

投的必要性,如果添加另一个类的层次变得更加清晰。考虑这组类来代替:

class Foo {} 
class Bar extends Foo {} 
class Baz extends Foo {} 

现在,如果你有Foo类型的引用,它可以指Foo例如,Bar实例或Baz实例。考虑下面的代码片段:

Foo f; 
if (Math.random() > 0.5) { 
    f = new Bar(); 
} else { 
    f = new Baz(); 
} 

你不能简单地调用f一个Bar,因为它可能的情况是f不是一个Bar,而是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块,我们有理由相信,fBar例如,尽管Java编译器不能肯定这一点。 (在这个例子中它看起来微不足道,但可能有成千上万的行和多个堆栈帧将if条件与演员分开)。因此,我们可以自信地演员。

但是,如果您错了,演员阵容实际上是无效的,那么您会在试图演员阵容中获得ClassCastException。这使问题更加清楚:不是在所讨论的实例没有所需功能的随机行上获取异常,而是发生转换尝试的位置。