我有以下指定的行為。
interface ValueEditorPopupView<T> {
void setValue(T value);
void setApplyEnabled();
}
abstract class ValueEditorPopup<T> implements ValueEditorPopupView<T> {
@Override
public void setApplyEnabled() {
System.out.println("In ValueEditorPopup.setApplyEnabled()");
}
}
class ListEditorTextField {
private final ValueEditorPopup<String> popup;
ListEditorTextField() {
popup = new ValueEditorPopup<>() {
@Override
public void setValue(String value) {
System.out.println("In Anonymous Class impl setValue()");
}
// When I add a method that is NOT defined in the abstract class/interface
// I get an error for using the diamond operator in the class declaration above
// "Cannot use '<>' due to non-private method which
// doesn't override or implement a method from a supertype"
// This error clears if I explicitly specify `new ValueEditorPopup<String>(){}`
// in the anonymous class instantiation or
// add `getValues` to the abstract class/interface.
public void getValues() {}
};
}
}
如上面代碼中的注釋所述,當我添加一個未在抽象類/介面中定義的方法時,在上面的類宣告中使用菱形運算子時出現錯誤:
“由于非私有方法不能覆寫或實作超型別中的方法,因此無法使用 '<>'”
new ValueEditorPopup<String>(){}如果我在匿名類實體化中明確指定或添加getValues到抽象類/介面,此錯誤就會清除。
我不明白為什么會導致錯誤以及為什么添加這些方法/型別會修復它。不知道我在這里缺少什么。
uj5u.com熱心網友回復:
這是設計使然,并在JLS §15.9.5中指定:
如果帶有 a 的類實體創建運算式
ClassBody使用菱形 (<>) 作為要實體化的類的型別引數,那么對于在 中宣告的所有非私有方法ClassBody,就好像方法宣告是用 注釋的@Override。
您的公共getValue方法不會覆寫超類中的任何內容,因此由于隱式添加@Override.
這樣做的理由是:
使用
<>時,推斷的型別引數可能與程式員預期的不同。因此,匿名類的超型別可能不像預期的那樣,并且匿名類中宣告的方法可能不會按預期覆寫超型別方法。將此類方法視為帶有注釋@Override(如果它們沒有顯式注釋@Override)有助于避免靜默不正確的程式。
我對此的解釋是,當你在匿名類中宣告公共方法時,它很可能會覆寫一個方法,因此編譯器會@Override在你使用<>. 這是為了確保您撰寫的方法確實覆寫了超類中的方法,因為如果不顯式寫下型別引數,編譯器可能會推斷出意外的型別,并且您撰寫的簽名實際上并沒有覆寫超類中的方法。(很遺憾,我想不出一個很好的例子)
很少需要在匿名類中宣告公共方法而不重寫。如果您想宣告一個方法,只需將其宣告為私有方法 - 無論如何您都不能從外部呼叫它,除非您將new運算式分配給 a var,這非常罕見。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/475138.html
上一篇:javatypegeneric:找一個例子來展示Function<?超級E,?extendsF>是比Function<E,F>更好的選擇?
