我正在准备OCA Java SE 7 Programmer I考试,这是个新手问题。我有一个例子,我不明白。下面的代码编译,但在运行时给出ClassCastException:
interface Roamable {
}
class Phone {
}
public class Tablet extends Phone implements Roamable {
public static void main(String... args) {
Roamable var = (Roamable) new Phone();
}
}
当我将Roamable var = (Roamable) new Phone();
更改为Roamable var = (Roamable) new String();
时,我立即得到编译错误。
两个问题:
1.为什么上面的代码可以编译?手机似乎与我的漫游无关?
1.为什么代码可以用new Phone()
编译,但不能用new String()
编译?
7条答案
按热度按时间hjzp0vay1#
为什么上面的代码可以编译?手机似乎与我的漫游无关?
是的,因为
Roamable
是一个接口,它可能会导致运行时异常,但不会导致编译时异常,因为即使Phone
没有实现Roamable
,Phone
的子类也可能实现,因此编译器除了在运行时之外没有办法知道它。它已经在Java语言规范中定义。在这里查看我的答案
为什么代码可以用new Phone()编译,但不能用new String()编译?
因为
class String
在java.lang
包中声明为public final class
。如**jls 8.1.1.2 final class
**部分所述:声明为final
的类不能被扩展,因此它没有任何子类。因此,编译器已经知道String
不能被扩展:因此,不可能存在子类来实现 interfaceRoamable
编辑:(回复您下面的评论)
让我们假设
B
是A
的一个子类,它实现了一个接口T
。现在声明:
基本上相同于:
在得出结论之前,让我们对
B
对象做同样的事情:所以,这里使用超类和子类的真实的原因是引用。第二个代码示例中的
aObj
类也是A
类的示例,但它也是实现了T
的B
类的示例。mfuanj7w2#
字符串是final的,所以没有办法将其转换为可漫游的。
icnyk63a3#
代码会编译,因为编译器允许强制转换为任何内容。这是程序员的一个显式操作,编译器假定您已经评估了风险并采取了适当的预防措施。
String
不是Roamable
的示例,因此不能将String
的示例分配给Roamable
引用。而这可以在编译时确定,所以它失败了。r7xajy2e4#
new Phone()
求值为类Phone
,它 * 可能 * 是Phone
的扩展,实现了Roamable
(就编译器而言)。如果将Phone设置为
final
类(如String),则会出现编译器错误。8nuwlpux5#
问得好
new Phone()
绝对不是Phone
的任何子类。但是这些信息丢失了,javac在那里看到的是Phone
类型,而不是 exactPhone
类型。相关规范:http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.5.1
如果S是final类(§8.1.1),则S必须实现T,
可以使用以下命令修改规范
如果表达式是类示例创建表达式(§15.9),则表达式的类型必须是T的子类型。
inn6fuwd6#
首先阅读有关Explicit and Implicit type casting的java。
从那以后,用户负责显式转换,当缩小对象关系时,说用户知道并罚款,他们因此失去了一些精度。然而,编译器仍然可以检测到一些显式的错误转换,并在某个时候抛出
CE: Type mismatch error
。除此之外,就由运行时ClassCastException
来处理它了。编译器可以检测以下显式强制转换情况。
编译器无法检测以下显式强制转换情况。
任何对象都可以被强制转换到任何接口而不会出现编译错误。
Why does this compile?
接口的引用可以强制转换为任何对象而不会产生编译错误。
0s7z1bwu7#
我想不需要太多的话。请简单地考虑下面的例子,记住***一个上级引用可以是指向它的一个子类的指针。
如果我们约束它,引用如何在正确的铸造之后引用对象?(在最后一行)