public class Base {
<T> List<? extends Number> f1() {return null;}
List<? extends Number> f2() {return null;}
<T extends Number> List<T> f3() {return null; }
}
class Derived extends Base {
List<String> f1() {return null;} // compiles fine !!!
List<String> f3() {return null; } // compiles fine !!!
// compile ERR: return type is incompatible with Base.f2()
List<String> f2() {return null;}
}
爲什麼覆蓋方法F1()和派生類F3()的定義,得到沒有編譯錯誤,如在派生類(其給出編譯錯誤「返回類型重寫F2()方法的定義與基本不相容。 f2()「)?當使用非泛型方法重寫泛型方法時,爲什麼副標記和未檢查的規則在返回類型上以這種方式工作?
JLS中的子簽名覆蓋規則允許覆蓋方法(在Derived類中)是非泛型的,而覆蓋方法(在Base類中)是泛型的。
未經檢查的覆蓋規則允許在子類List<String>
中生成返回類型,而不是基類中的List<T>
。
但我無法解釋下面的行爲差異,我不明白爲什麼f1()和f3()覆蓋Derived類中的定義已成功編譯(在Eclipse,SE8上),忽略了有界類型參數f3()和有界通配符f1()!
P.S.我的猜測 - 在Derived編譯器中的f1()和f3()中,將這兩種方法視爲僅返回「raw」。List - 編譯器首先進行擦除(此時僅在Derived !?中),然後將Derived中的這些擦除方法與未擦除(到目前爲止)在Base中的方法。現在未檢查覆蓋規則是可以的(並且不需要檢查邊界 - 它根本不可能),編譯器決定這是正確的覆蓋並且編譯進一步...以及Base.f1()和Base中編譯泛型末尾的某處.f3()也刪除:)))
This SO answer也增加了這個主題的想法。