我看到了這個問題,但它似乎沒有回答下面的兩種情況,也沒有提到任何進一步的檔案,我很想閱讀。
我有以下代碼片段:
public static void main(String[] args) {
//編譯時OK
//運行時ClassCastException。
Child noWarnings = (Child)getParent()。
//vs...
///編譯時失敗。
Child compileTimeFailure = new Parent()。
}
private static Parent getParent() {
return new Parent()。
}
private static class Parent { }
title class_">Child extends Parent { }
片段第4行的代碼沒有產生警告,但卻產生了ClassCastException。為什么編譯器不能對其進行型別檢查呢?
這就更奇怪了。
如果我們增加一層間接性,這就變得更加奇怪了:
public static void main(String[] args) {
//編譯時OK
//運行時ClassCastException。
Boxed noWarnings = new Boxed((Child)getParent())。
//vs...
//編譯時沒有問題,但發出的警告是正確的。
//運行時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 Parent Private Child extends Parent { }
編譯器不允許第一個例子,但允許第二個例子,這似乎是不直觀的。
如果有任何關于這兩種情況的線索,我們將非常歡迎。
uj5u.com熱心網友回復:
為什么編譯器無法對其進行型別檢查?
有些 Parent實體是Child的實體,因為所有的Childs都是Parents。編譯器不知道將被回傳的實體是否是一個Child;但它可能是。所以它允許它。
事實上,正如Stephen C指出的那樣,JLS不允許編譯器將此稱為編譯錯誤。
具體而言,語言規范說:
如果運算元的編譯時型別不能通過鑄造轉換(§5.5)轉換到由鑄造運算子指定的目標型別,那么就會發生編譯時錯誤。
(它還描述了另一種在鑄造運算式中發生編譯時錯誤的情況;但是這些在這里并不適用,因為沒有一個或多個 AdditionalBound 項)。
Parent可以通過narrowing reference conversion轉換為Child,因此不會發生編譯時錯誤。
Boxed classCastWarning = new Boxed((Child) new Parent());
這很明顯會失敗。new Parent()不是Child的實體,它是Parent的實體。
但是編譯器實際上并沒有考慮到關于new Parent()的任何東西,除了它是一個Parent型別的運算式,它必須允許你投遞到一個Child。
但是這并不是說IDE等工具不允許給你一個警告(甚至是一個錯誤,如果你有這樣的配置):通過靜態分析,很明顯new Parent()將是Parent的一個實體(因為那是所有new Parent()可以成為的),所以將其轉換到一個子類將會失敗。你的工具可以告訴你一些在規范中沒有具體涵蓋的東西。
uj5u.com熱心網友回復:
除了現有的答案之外,我想強調一下在編譯時不容易計算這個例外的原因。
下面的例子也是來自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() 。
可著色的c。
//下面的內容在運行時可能會導致錯誤,因為
//我們不能確定它們會成功,這種可能性。
//是由鑄模建議的:
cp = (ColoredPoint)p; //p可能沒有參考一個的
//物件是一個ColoredPoint。
//或ColoredPoint的子類。
// This wont throw casts exception as references to object is valid[/span].
Point refPoint = new ColoredPoint()。
cp = (ColoredPoint)refPoint; //完全有效 //p可能不是Colorable
。
//以下內容在編譯時是不正確的,因為 //以下內容在編譯時是不正確的。
//它們不可能成功,正如文中所解釋的那樣: //它們不可能成功。
Long l = (Long)p; //編譯時錯誤 #1
EndPoint e = new EndPoint()。
c = (Colorable)e; //編譯時錯誤#2
這個例子在大多數情況下是不言自明的,但你可以進一步閱讀上面的檔案。
uj5u.com熱心網友回復:
ClassCastExceptions從不在編譯時發生。所有的例外都發生在運行時。你可以檢查你的IDE的設定,在編碼時獲得提示。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/331559.html
標籤:
下一篇:如何從for回圈創建一個字典
