interface Printable {}
class BlackInk {}
public class Main {
public static void main(String args[]) {
Printable printable = null;
BlackInk blackInk = new BlackInk();
printable = (Printable)blackInk;
}
}
如果编译并运行前面的代码,结果是printable=(printable)blackInk处的ClassCastException
。但是,如果将Printable更改为类,它就不会编译,因为blackInk不能转换为Printable。当Printable是一个接口时,它为什么要编译?
类型转换发生在运行时(记住运行时多态性)。在编译时,编译器没有发现代码有任何错误,并进行编译,在运行时,它试图将castblackink
键入printable
,但无法执行,因为blackink
没有实现printable
,因此出现错误。
根据java语言规范部分:5.5.1参考类型铸造:
对于编译时引用类型S
(源)和编译时引用类型T
(目标);当从S
转换为T
时,如果S
是类
类型
>
如果T
是Class
类型:
>
class S{}
class T extends S{}
////
S s = new S();
T t = (T)s; // run time ClassCastException will happen but no compile time error
如果T
是接口
类型:
S
不是final
类,那么,如果存在T
的超类型X
,以及S
的超类型Y
,那么X
和Y
都是可证明的不同参数化类型,X
和Y
的擦除是相同的,出现编译时错误。否则,cast在编译时总是合法的(因为即使S
没有实现T
,S
的子类也可能实现)对于您的情况,即使在编译时检测到类转换,也会在运行时
中检测到Interface转换。
编译器不知道这是行不通的:您可能有一个子类BlackInk,它实现了可打印。那演员就没事了。
在编译器知道它无法工作的情况下,您将得到一个错误。
例如,如果将BlackInk设置为final
(这样就不会有子类),则会出现错误。
问题内容: interface Printable {} class BlackInk {} 如果前面的代码已编译并运行,则结果为ClassCastException 。但是,如果将Printable更改为一个类,则因为blackInk无法转换为Printable而无法编译。当Printable是接口时,为什么要编译? 问题答案: 编译器不知道这是行不通的:您可能具有实现Printable的Bla
问题内容: 显然,这会导致编译错误,因为Chair与Cat无关: 为什么当我将Cat引用转换为不相关的接口Furniture时,我只能在运行时得到一个异常,而编译器显然可以告诉Cat没有实现Furniture? 问题答案: 编译的原因 是你可能会拥有 如果创建实例,则可以将其分配给,并且可以将该实例强制转换为。换句话说,某些子类型可能会实现该接口。 在第一个例子中 除非自身从扩展,否则某些子类型不
显然,这会导致编译错误,因为椅子与Cat无关: 那么,为什么只有在运行时,当我将Cat引用转换到不相关的接口家具时,才会出现异常,而编译器显然可以看出Cat没有实现家具?
问题内容: 因此,如果我有一个,由于某种原因,如果我在另一段代码(如)中引用它,则在编译过程中它不会内联到代码中。因此,它不是在被编译之后而是。 问题答案: 您不是编译时间常数,因为JLS 表示 不是。只能在常量表达式中使用的类型是基本类型和。 它的意义是,一个实例(通常)具有语义上重要的对象标识,该标识将其与其他实例区分开。此对象标识不能编码在类文件中……至少,不能用当前的类文件格式编码。(如果
问题内容: 我正在尝试使用泛型实现以下结构。收到编译器错误,无法找出原因。 这个想法是译者使用T作为字典中键的类型。例如,可以是字符串或枚举。子类提供具体的字典。 但是它失败,因为:“类型’String’不符合协议’Hashable’” 但是String符合Hashable。它也不适用于Int,后者也符合Hashable。 如果删除类型约束,则仅用于测试(在此我还必须禁用字典,因为我不能在其中使用
我有一个简单的测试设置,如 但当我尝试编译测试时,我会遇到53个错误,比如 实际上并没有传达任何关于问题所在的有用信息。我只能假设在我的构建中没有正确配置某些内容。sbt文件或其他地方。 这段代码确实曾经工作过,在我清理东西的过程中,事情发生了变化,现在它被破坏了,没有好的诊断。 有人能提出要找的东西吗?