英文:
Why casting to unrelated interface produce ClassCastException instead of compile time exception?
问题
为什么在这个代码片段中,尽管Tree接口与Bug类无关,但它不会产生编译时异常?
interface Tree {}
class Bug {
public static void main(String[] args) {
Bug bug = new Bug();
Tree tree = (Tree) bug;
}
}
英文:
Why in this snippet while Tree interface is not related to Bug class it does not produce compile time exception?
interface Tree {}
class Bug {
public static void main(String[] args) {
Bug bug = new Bug();
Tree tree = (Tree) bug;
}
}
答案1
得分: 2
将 Bug
标记为 final
,你将会得到预期的编译错误。
这是因为 Bug
可能有一个子类实际上实现了 Tree
接口。如果 Bug
实际上存储了对该子类实例的引用,那么类型转换将会成功。由于存在类型转换可能成功的情况,编译器不会阻止你进行类型转换。
在大多数情况下,你可以从任何非 final 类型转换到任何接口。根据 JLS §5.5.1,当你尝试将引用类型为 S
的变量转换为接口 T
时:
如果 S 不是 final 类型(§8.1.1),那么如果存在接口
T
的超类型X
,和变量S
的超类型Y
,使得X
和Y
都是可以证明不同的参数化类型,并且X
和Y
的擦除操作是相同的,那么在编译时会产生错误。否则,在编译时转换总是合法的(因为即使
S
没有实现T
,S
的子类可能会实现)。
英文:
Mark Bug
as final
and you will get your compiler error as expected.
This is because Bug
could have a subclass that does implement Tree
. If bug
actually stores a reference to an instance of that subclass, then the cast will succeed. Since there is a chance that the cast can succeed, the compiler doesn't stop you from casting.
In most cases, you can cast from any non-final class to any interface. According to the JLS §5.5.1, when you try to cast a variable of reference type S
to interface T
:
> If S is not a final class (§8.1.1), then, if there exists a supertype X of T, and a supertype Y of S, such that both X and Y are provably distinct parameterized types, and that the erasures of X and Y are the same, a compile-time error occurs.
>
> Otherwise, the cast is always legal at compile time (because even if S does not implement T, a subclass of S might).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论