转换为未实现的接口编译

时间:2014-12-25 17:33:27

标签: java class interface reference

我不确定我理解下面第1行的代码?

interface Talkable{ }
class Device{}
class Phone extends Device implements Talkable{}


Talkable d = (Talkable) new Device(); //line 1
Talkable p = new Phone(); //line 2

我理解line2,因为Phone实现了Talkable,但Device和Talkable是无关的,line1如何合法?

4 个答案:

答案 0 :(得分:18)

编译器接受此原因的原因在JLS section 5.5.1(粗体相关部分)中进行了解释:

  

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

     

如果S是班级类型:

     
      
  • 如果T是类类型,则为| S | &lt ;: | T |,或| T | <:| S |。否则,将发生编译时错误。
  •   
     

此外,如果存在T的超类型X和S的超类型Y,使得X和Y都可证明是不同的参数化类型(§4.5),并且X和Y的擦除是相同的,发生编译时错误。

     
      
  • 如果T是接口类型:

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

           

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

    •   
  •   

在您的情况下,java.lang.ClassCastException将在运行时抛出,因为Device无法转换为Talkable。但是在程序执行之前,编译器允许转换,因为可能有Device的子类实现Talkable

答案 1 :(得分:9)

实际上,在Java中,完全有效将一个相关类型转换为另一个<(即使转换没有意义)。如果类型不是兼容,则在运行时会出现错误。

例如:

    public static void main(String[] args) {
        String s = (String) new Object();
        System.out.println(s.intern());

    }

编译正常,但在运行时

期间提供Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String at Sample.main(Sample.java:5)

答案 2 :(得分:6)

第1行将抛出运行时异常。如果可以成功完成转换,编译器不会在编译时检查。这就是为什么有时建议先使用instanceof运算符进行检查。

通常,您始终可以将x类型的变量A强制转换为任何接口C,因为可能存在类B extends A implements C或类{{ 1}}

将类B implements A, C的变量x强制转换为任何类A时也是如此,因为不存在子类D,因为类可能不存在扩展多个类。

答案 3 :(得分:3)

实际上,在第一行,代码明确地&#34;告诉&#34;编译器右侧的对象是左侧的类型对象(这称为type casting)。这在编译时对Java中的任何两种类型都有效,但如果类型不相关,则会出现运行时错误(将抛出Exception。)

在第二行,所做的工作在编译时和运行时都是有效的,因为Phone是它扩展和/或实现的任何类型,所以实际上,Phone是Talkable(和Device)。