1

有没有人有任何可行的策略来解决铸造/上转型问题?我理解何时允许向上转换和向下转换,但是当问题往往涉及多个对象时,我往往很快就会感到困惑。例如,找到这样一个问题的答案的最佳方法是什么:

问题:编译以下程序的结果是什么:

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;        
    }   
}

我对答案并不感兴趣,但对解决问题的方法更感兴趣。有什么方法/策略可以用来解决像上面这样的向上转换/向下转换问题吗?例如,可以在纸上绘制参考/对象,以便我可以获得视觉表示,这有帮助吗?

谢谢

4

4 回答 4

3

有一些简单的规则

  • 您可以转换为类前身(一直到对象)(从不失败)
  • 您可以转换为子类 - 这可能会在运行时失败
  • 您可以从实现它的类转换为接口(永不失败)
  • 您可以从 interafce 转换为 iplemneting 类 - 这可能会在运行时失败

前两条规则也适用于 ti 接口。

您可以绘制UML 类图 以将其可视化(仅使用 implements = implementations, extends realetions),沿箭头方向导航该图将是安全的。以另一种方式导航将是运行时 usafe。并且在没有扩展/实现关系的情况下进行导航是不可能的。

于 2011-12-27T15:23:06.027 回答
3

这是一篇关于向上转换和向下转换的精彩文章。

引用文章——

首先,你必须明白,通过强制转换你实际上并没有改变对象本身,你只是给它贴上了不同的标签。

只需问自己一个问题“对象的类型是什么?” 然后请记住,将其强制转换为类层次结构中的任何前身类(包括接口)是合法的。

在您的情况下,您正在创建 2 个对象, aBaseDerived. Base可以标记为或Inter并且可以标记Base为或。因此,您的代码将编译得很好。但是在运行时,当您尝试强制转换为 a时,您会得到一个 ClassCastException。DerivedInterBaseDerivedBase bDerived bd

于 2011-12-27T15:23:39.433 回答
1

如果被操作的对象在同一层次结构中,强制转换肯定会编译,但它可能在运行时失败。

例如:

class Animal { }
class Dog extends Animal { }
class Bulldog extends Dog { }

如果你写:

Animal animal = new Animal();
Dog d = (Dog) animal;

上面的代码会编译,但会在运行时失败。因为编译器所能做的就是检查这两种类型是否在同一个继承树中。编译器允许可能在运行时工作的东西。但是如果编译器确定某些东西永远不会工作,它会在运行时本身抛出错误。例如

Animal animal = new Animal();
Dog d = (Dog) animal;
String s = (String) animal;

这肯定会失败,因为编译器知道 String 和 Dog 不在同一个层次结构中。

同样的规则也适用于接口。

希望能帮助到你。

于 2011-12-27T15:24:19.400 回答
1

对我来说,我想先画出这些类型的层次结构。对于您的问题,类型的“级别”是:


Inter(高于)

Base(高于)

Derived


对象的“级别”在其创建时就已确定,对象只能“上升”而不能下降,具体取决于其创建级别。例如,Objectb是作为Base对象创建的,因此它处于Base. 无论使用什么类型来描述 b,您都可以很容易地发现bcan upcast toInter但不是 downcast to 。DerivedifInter用于描述 b,因为它的创建级别是Base,所以可以向下转换为Base

于 2011-12-27T15:29:45.793 回答