Java将对象转换为未实现的接口
我在学习书中发现了以下问题,有点困惑:
给定以下代码,如果用于替换/* INSERT CODE HERE */
,哪个选项将启用Roamable
类型的引用变量来引用Phone
类的对象? (选择1个选项。)
interface Roamable{} class Phone {} class Tablet extends Phone implements Roamable { //INSERT CODE HERE }
选项包括:
-
Roamable var = new Phone();
-
Roamable var = (Roamable)Phone();
-
Roamable var = (Roamable)new Phone();
- 由于接口
Roamable
和类Phone
不相关,因此Roamable
类型的引用变量不能引用Phone
类的对象。
我认为正确的选项是4,但它说它是3。
但是, Phone
并没有实现Roamable
接口,所以你不能施展,可以吗?
正确的答案是3
:编译器只看到一个Phone
被Roamable
转换为Roamable
并且该Phone
不是final,因此它认为正在转换的对象虽然被称为Phone
,但它可能是实现Roamable
的Phone
的子类,因此不会发出编译时错误或警告。
根据JLS第5章
5.5.1。 参考类型铸造
给定编译时引用类型S(源)和编译时引用类型T(目标),如果由于以下规则而没有发生编译时错误,则从S到T存在转换转换。 如果T是接口类型:
如果S不是最终类(第8.1.1节),那么,如果存在T的超类型X和S的超类型Y,那么X和Y都可certificate是不同的参数化类型,并且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 }
答案是4
如
1 is incorrect(explanation --> 4) 2 is incorrect syntax 3 is incorrect typecast.
请注意, 答案3只要是编译就有效。 当你说你有一个Phone
类的实例时,你可以输入cast到Tablet
(类似于你可以将Object
为String
)。 而且由于Tablet
实现了Roamable
你可以很好地使用Roamable
引用来引用它。 Problem will occur at runtime
因为Object
实际上是Phone
类型。
这只是一个允许成功编译的链接模式(在当前上下文中)。 但正如波希米亚人在他的答案中提到的那样
如果我们对编译时间引用S(非final)进行类型转换以编译时间引用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 }