有没有人有解决演员/转播问题的可行策略?我理解允许向上转换和向下转换时,但当问题涉及多个对象时,我会很快感到困惑。例如,找到这样一个问题答案的最佳方法是什么:
问题:编译以下程序的结果是什么:
interface Inter{}
class Base implements Inter{}
class Derived extends Base{}
class ZiggyTest2{
public static void main(String[] args){
Base b = new Base();
Derived d = new Derived();
Inter i = (Base)b;
i = (Base)d;
Derived bd = (Derived)b;
b = (Base)i;
}
}
我对答案并不感兴趣,但更多的是解决问题的方法。我可以使用任何方法/策略来解决上面的上行/下行问题吗?例如,可以在纸上绘制参考/对象,以便我可以获得视觉表示并且可以帮助吗?
由于
答案 0 :(得分:3)
这是关于向上转发和向下转发的great article。
引用文章 -
首先,你必须明白,通过投射你实际上并没有改变对象本身,你只是用不同的方式标记它。
问自己一个问题“对象的类型是什么?”然后记住将它转换为类heirarchy(包括接口)中的任何前任类是合法的。
在您的情况下,您要创建2个对象,Base
和Derived
。 Base
可以标记为Inter
或Base
,Derived
可以标记为Inter
,Base
或Derived
。所以,你的代码编译得很好。但是在运行时,当您尝试将Base b
强制转换为Derived bd
时,您将获得ClassCastException。
答案 1 :(得分:2)
有一些简单的规则
前两个规则也适用于接口。
您可以绘制UML class diagram以使其可视化(仅使用implements = realizes,扩展重新定位),在箭头方向上导航将是安全的。导航另一种方式是运行时usafe。并且没有扩展/实现关系的导航是不可能的。
答案 2 :(得分:1)
如果正在操作的对象位于同一层次结构中,则会进行转换以确保编译,但在运行时可能会失败。
E.g:
class Animal { }
class Dog extends Animal { }
class Bulldog extends Dog { }
如果你写:
Animal animal = new Animal();
Dog d = (Dog) animal;
上面的代码将编译,但它会在运行时失败。因为所有编译器都可以检查这两种类型是否在同一继承树中。编译器允许可能在运行时工作的内容。但是如果编译器确定某些东西永远不会工作,它将在运行时自身抛出错误。 E.g。
Animal animal = new Animal();
Dog d = (Dog) animal;
String s = (String) animal;
这肯定会失败,因为编译器知道String和Dog不在同一层次结构中。
同样的规则也适用于接口。
希望它有所帮助。
答案 3 :(得分:1)
对我来说,我想首先绘制这些类型的层次结构。对于您的问题,类型的“级别”是:
Inter
(高于)
Base
(高于)
Derived
对象的“级别”在其创建时确定,并且对象只能根据其创建级别“向上”而不是向下。例如,对象b
被创建为Base
对象,因此它处于Base
级别。无论用什么类型描述b,您都可以轻松找到b
可以向Inter
转播,但不能向下转发到Derived
。如果Inter
用于描述b,由于其创建级别为Base
,您可以将其向下转换为Base
。