我不确定我理解下面第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如何合法?
答案 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
)。