我见过这个问题,但它似乎没有回答以下两种情况,也没有引用任何进一步的文档,我很想阅读这些文档。
我有以下代码片段:
public static void main(String[] args) {
// compile-time OK
// run-time ClassCastException
Child noWarnings = (Child) getParent();
// vs...
// compile-time failure
Child compileTimeFailure = new Parent();
}
private static Parent getParent() {
return new Parent();
}
private static class Parent { }
private static class Child extends Parent { }代码段第4行上的代码生成,没有警告,但结果是ClassCastException。为什么编译器不能对此进行类型化?
如果我们加上一层间接的话,这就更奇怪了:
public static void main(String[] args) {
// compile-time OK
// run-time ClassCastException
Boxed noWarnings = new Boxed((Child) getParent());
// vs...
// compile-time OK, but warning is emitted correctly
// run-time ClassCastException
Boxed classCastWarning = new Boxed((Child) new Parent());
}
private static Parent getParent() {
return new Parent();
}
private static class Boxed {
public Boxed(Child data) {
}
}
private static class Parent { }
private static class Child extends Parent { }编译器不允许第一个示例,但允许第二个示例,这似乎是不直观的.
任何关于这两种情况的说明都将是最受欢迎的。
发布于 2021-09-21 15:43:41
为什么编译器不能对此进行类型化?
一些Parent实例是Child的实例,因为所有的Child都是Parent。编译器不知道将返回的实例是否为Child,但可能是。所以它允许它。
事实上,作为斯蒂芬C指出,JLS不允许编译器将其称为编译错误。
具体来说,语言规范说
如果操作数的编译时类型不能通过转换(§5.5)转换为强制转换操作符指定的目标类型,则会发生编译时错误。
(它还描述了转换表达式中出现编译时错误的另一种情况;但这些错误在这里不适用,因为没有一个或多个AdditionalBound术语)。
Parent可以由变窄参考转换转换为Child,这样编译时错误就不会发生.
Boxed classCastWarning = new Boxed((Child) new Parent());
这显然会失败。new Parent()不是Child的实例,而是Parent的实例。
但是编译器实际上并没有在强制转换的上下文中考虑任何关于new Parent()的内容,除了它是Parent类型的表达式之外,它必须允许您将其转换为Child。
但这并不是说不允许像IDE这样的工具给您一个警告(甚至是一个错误,如果您有这样的配置):通过静态分析可以清楚地看到,new Parent()将完全是Parent的一个实例(因为这就是new Parent()所能做到的),所以将其转换到子类将失败。您的工具可以告诉您规范中没有具体说明的内容。
发布于 2021-09-21 16:21:40
除了现有的答案之外,我还想强调为什么在编译期间不容易计算这个异常。
下面的例子也来自于https://docs.oracle.com/javase/specs/jls/se11/html/jls-5.html#jls-5.5的摘录,还有我的一些补充。
class Point { int x, y; }
interface Colorable { void setColor(int color); }
class ColoredPoint extends Point implements Colorable {
int color;
public void setColor(int color) { this.color = color; }
}
final class EndPoint extends Point {}
class Test {
public static void main(String[] args) {
Point p = new Point();
ColoredPoint cp = new ColoredPoint();
Colorable c;
// The following may cause errors at run time because
// we cannot be sure they will succeed; this possibility
// is suggested by the casts:
cp = (ColoredPoint)p; // p might not reference an
// object which is a ColoredPoint
// or a subclass of ColoredPoint
// this wont throw casts exception as references to object is valid
Point refPoint = new ColoredPoint();
cp = (ColoredPoint)refPoint; // perfectly valid
c = (Colorable)p; // p might not be Colorable
// The following are incorrect at compile time because
// they can never succeed as explained in the text:
Long l = (Long)p; // compile-time error #1
EndPoint e = new EndPoint();
c = (Colorable)e; // compile-time error #2
}
}这个示例本身在大多数情况下都是不言自明的,但是您可以进一步阅读上面的文档。
发布于 2021-09-21 15:44:27
ClassCastExceptions从不在编译时发生。所有异常都发生在运行时。您可以在编写代码时检查IDE的设置以获得提示。
https://stackoverflow.com/questions/69271809
复制相似问题