我在学习书中发现了以下问题并且有点困惑:
给定以下代码,如果用于替换/* 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
界面,所以你不能投,你可以吗?
答案 0 :(得分:11)
正确的答案是3
:编译器只会看到Phone
被投射到Roamable
并且Phone
不是最终的,所以它认为正在强制转换的对象,虽然称为Phone
,但它可能是 实现Phone
的{{1}}的子类,因此不会发出编译时错误或警告。
<强> 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,否则会发生编译时错误。
以下代码编译:
Roamable
答案 1 :(得分:1)
答案是 4
作为
1 is incorrect(explanation --> 4)
2 is incorrect syntax
3 is incorrect typecast.
请注意, answer 3 只要是编译就有效。当您说有Phone
类的实例时,您可以输入强制转换为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
}