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

时间:2014-02-16 14:10:56

标签: java interface casting

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

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

interface Roamable{}
class Phone {}
class Tablet extends Phone implements Roamable {
    //INSERT CODE HERE
}

选项包括:

  1. Roamable var = new Phone();
  2. Roamable var = (Roamable)Phone();
  3. Roamable var = (Roamable)new Phone();
  4. 因为接口Roamable和类Phone不相关,所以引用变量 类型Roamable的类型不能引用类Phone的对象。
  5. 我认为正确的选项是4,但它说它是3。

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

2 个答案:

答案 0 :(得分:11)

正确的答案是3:编译器只会看到Phone被投射到Roamable并且Phone不是最终的,所以它认为正在强制转换的对象,虽然称为Phone,但它可能是 实现Phone的{​​{1}}的子类,因此不会发出编译时错误或警告。

根据JLS chapter 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,否则会发生编译时错误。


以下代码编译:

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
}