Java将对象转换为未实现的接口

Erd*_*inc 8 java casting interface

我在学习书中发现了以下问题,有点困惑:

给定以下代码,如果用于替换哪个选项,/* INSERT CODE HERE */将启用类型的引用变量Roamable来引用Phone类的对象 ?(选择1个选项.)

interface Roamable{}
class Phone {}
class Tablet extends Phone implements Roamable {
    //INSERT CODE HERE
}
Run Code Online (Sandbox Code Playgroud)

选项包括:

  1. Roamable var = new Phone();
  2. Roamable var = (Roamable)Phone();
  3. Roamable var = (Roamable)new Phone();
  4. 因为接口Roamable和类Phone是不相关的,所以类型的引用变量Roamable不能引用类的对象Phone.

我认为正确的选项是4,但它说它是3.

但是,Phone没有实现Roamable界面,所以你不能施展,可以吗?

Boh*_*ian 11

正确的答案是3:编译器只能看到一个Phone被强制转换为一个RoamablePhone不是终点,所以它认为该对象正投,虽然被称为Phone可能是一个子类,Phone执行Roamable,所以没有编译时错误或发出警告.

根据JLS第5章

5.5.1.参考类型铸造

给定编译时引用类型S(源)和编译时引用类型T(目标),如果由于以下规则而没有发生编译时错误,则从S到T存在转换转换.如果T是接口类型:

如果S不是最终类(第8.1.1节),那么,如果存在T的超类型X和S的超类型Y,则X和Y都是可证明的不同参数化类型,并且X的擦除和Y相同,发生编译时错误.

否则,强制转换在编译时总是合法的(因为即使S没有实现T,S的子类也可能).

如果S是最终类(第8.1.1节),那么S必须实现T,否则会发生编译时错误.


以下代码编译:

interface Roamable{}
class Phone {}
class Tablet extends Phone implements Roamable {
    Roamable var = (Roamable)new Phone(); // Compiles
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一本学习书上的问题,如果真的像书中那样写,那么书中的答案是错误的,正确答案是 4。问题写得不好。无论哪种情况,这本书都是错误的。 (2认同)

Ani*_*kur 1

答案是4

作为

1 is incorrect(explanation --> 4)
2 is incorrect syntax
3 is incorrect typecast.
Run Code Online (Sandbox Code Playgroud)

请注意,答案 3只要与编译有关,就有效。当你说你有一个类的实例时,Phone你可以输入cast into Tablet(类似于你可以cast Objectto String)。由于Tablet实现了,Roamable您可以很好地使用Roamable引用来引用它。Problem will occur at runtime因为它Object确实是类型Phone

这只是允许成功编译的链接模式之一(在当前上下文中)。但正如波西米亚人在他的回答中一般提到的

如果我们将编译时引用 S(非最终)类型转换为编译时引用 T,则编译将成功,如下所示even if S does not implement T, a subclass of S might。如果 S 是最终类,则 S 必须实现 T,否则会发生编译时错误。

实际上根本不需要Tablet类扩展Phone类。只要Phone类not final编译就会成功

interface Roamable{}
class Phone {}
class Tablet implements Roamable {
    Roamable var = (Roamable)new Phone(); // Compiles
}
Run Code Online (Sandbox Code Playgroud)