OOP,接口,对象和铸造

时间:2012-05-14 18:03:14

标签: java oop

我正在查看一些过去的OOP考试试卷,我将非常感谢您理解以下代码。问题是,鉴于第一个代码块并且Sandwich实现了Edible,以下哪些陈述是合法的?

Sandwich sub = new Sandwich();
Rectangle cerealBox = new Rectangle(20,30,20,10);
Edible e = null;

e = sub;
sub = e;
sub = (Sandwich) e;
sub = (Sandwich) cerealBox;
e = cerealBox;
e = (Edible) cerealBox;
e = (Rectangle) cerealBox;
e = (Rectangle) null;
e = (Edible) sub;
cerealBox = (Rectangle) new Object();

我目前的理解是第一个陈述是正确的,因为sub具有构成可食用对象所需的元素,因此它对于第二个语句不起作用。并且使用第三个语句转换确实允许这个工作。但第四个不是因为cerealBox不适用于三明治。然后最后两个因为铸造而起作用。但显然第六个有效吗?

对于我所知道的可怕解释感到抱歉,我们将不胜感激。

2 个答案:

答案 0 :(得分:6)

Java中的继承和接口实现据说代表了“is-a”关系。也就是说,如果Boy继承自Person,那么Boy就是Person。因此,可以将视为 a Person(因为它是)。这尤其意味着可以将其分配给类型为Person的实例。

有了这个,我们可以决定

  1. e = sub编译并运行正常。的 [OK]
  2. 另一方面,
  3. sub = e不编译:一个is-a关系不能被逆转。的 [!]
  4. sub = (Sandwich) e 强制以上内容通过显式转换进行编译。此外,由于此时e 包含三明治(来自赋值1),因此此转换也会在运行时成功。的 [OK]
  5. sub = (Sandwich) cerealBox - 由于没有从RectangleSandwich的有意义转换,因此无法编译。的 [!]
  6. e = cerealBox - 同样在这里,出于同样的原因。的 [!]
  7. e = (Edible) cerealBox这里,Java编译器投降:它允许强制转换,即使我们(程序员)知道它不能成功,因为cerealBox中包含的对象没有实现Edible - 但编译器无法知道这一点:可以想象,其中包含的对象可以从Rectangle派生(因此可分配给cerealBox),而也< / em>实施Edible

    所以编译器默认。但在运行时,您将获得ClassCastException

    请注意此声明与4的不同之处:编译器知道cerealBox不能包含Sandwich。但它可以包含Edible的内容。为什么?因为Java是单继承(并且Rectangle不从Sandwich继承),但允许从多个接口扩展。的 [C]

  8. e = (Rectangle) cerealBox失败,因为演员实际上完全没有意义(cerealBox已经是Rectangle类型),剩下的陈述相当于5. [!]
  9. e = (Rectangle) null失败,即使null 可以分配给Edible对象。但是演员因为5无效而使其无效。的 [!]
  10. e = (Edible) sub有效,等同于1.然而,强制转换是完全冗余的,因为Java会在继承层次结构中隐式执行向上转换。的 [OK]
  11. cerealBox = (Rectangle) new Object()编译,并在运行时崩溃。原因类似于6:ObjectRectangle的基类;因此,一个对象可以包含一个Rectangle实例,这将使该语句成功(参见3中的一个示例)。

    是的,编译器有点愚蠢 - 可以看到正在投射的对象 - new Object() - 绝不可能是Rectangle。但编译器不进行此分析,因为在一般情况下这是不可能的。的 [C]

  12. 键:[确定] =编译,运行无错误。 [C] =编译,崩溃。 [!] =无法编译。

    正如您所看到的,哪些语句是“合法的”并不能完全消除它:其中一些语句会编译,但会在运行时产生异常。他们合法吗?

答案 1 :(得分:1)

第六个不起作用。 Rectangle不实现Edible,因此无法将其转换为它。

编辑:请参阅Vulcan的注释,了解IDE允许的原因。您将收到运行时错误。