簡體   English   中英

Java泛型未經檢查的覆蓋

[英]Java generics unchecked override

當使用具有具體類型的方法(滿足該通用類型)來實現具有通用類型的接口方法時,會發生未經檢查的覆蓋警告。

這是一個示例代碼:

interface SomeType{}

class Impl1 implements SomeType{}

interface SomeInterface{
    <T extends SomeType> T justDoIt();
}

class SomeInterfaceImpl implements SomeInterface{
    public Impl1 /*here i get the warning*/ justDoIt(){
        return null;
    }
}

警告說:返回類型需要未經檢查的轉換...任何人都可以解釋一下。 我知道類型擦除,但這在編譯時可以驗證,沒有未經檢查的強制轉換。

重要的問題。 什么是實現此目標的正確方法? 鑒於我希望能夠實現SomeInterface但要提供編譯時具體類型的類型安全性(不使用SomeType但要使用具體SomeType后代)?

更新:這是我想做的

interface SomeType{

}

class Impl1 implements SomeType{

}

interface SomeInterface{
    SomeType convert(String param);
    String convert(SomeType param);
}

class SomeInterfaceImpl implements SomeInterface{
    public Impl1 justDoIt(){
        return null;
    }

    @Override
    public Impl1 convert(String param) {
        return null;
    }

    @Override
    public String convert(Impl1/*compile error right here*/ param) {
        return null;
    }
}

我希望現在我的初衷是明確的。 我需要為轉換器提供通用接口...

對於方法的返回,只需在接口中定義justDoIt方法即可返回SomeType 然后,在SomeInterfaceImpl ,您可以聲明返回Impl1沒問題。

interface SomeInterface{
    SomeType justDoIt();
}

class SomeInterfaceImpl implements SomeInterface{
    public Impl1 justDoIt() {
        return null;
    }
}

Java語言規范對此進行了解釋(強調我,在花括號[]之間添加了注釋):

9.4.1。 繼承與覆蓋

9.4.1.2。 覆蓋要求

§8.4.8.3中指定了接口方法的返回類型與任何重寫的接口方法的返回類型之間的關系。

(......)

8.4.8.3。 覆蓋和隱藏要求

如果返回類型為R1的方法聲明d1覆蓋或隱藏了返回類型為R2的另一個方法d2的聲明,則d1必須是d2的返回類型可替換的(第8.4.5節 ),否則會發生編譯時錯誤。

8.4.5。 方法結果

如果滿足以下任何條件,則返回類型為R1的方法聲明d1可替換為返回類型為R2的另一個方法d2:

  • 如果R1為空,則R2為空。

  • 如果R1是原始類型,則R2與R1相同。

  • 如果R1是引用類型,則下列條件之一為真:

    • 適應d2類型參數(第8.4.4節 )的R1是R2的子類型。 [這是你的情況]

    • 可以通過未經檢查的轉換將R1轉換為R2的子類型(第5.1.9節 )。

    • d1與d2(第8.4.2節 )的簽名不同 ,並且R1 = | R2 |。


對於方法重寫,請注意這里的簽名無效,因此會出現編譯器錯誤。 具有String參數和Object參數並不相同,這在方法重載時很容易驗證:

class Foo {
    public void bar(String o) {
    }
    public void bar(Object o) {
    }
}

在這種情況下,您不能進行此類覆蓋,只需按原樣聲明參數即可:

@Override
public String convert(SomeType param) {
    return null;
}

您需要通用類型,而不是通用方法:

interface SomeType {
}

class Impl1 implements SomeType {
}

interface SomeInterface<T extends SomeType> {
    T convert(String param);
    String convert(T param);
}

class SomeInterfaceImpl implements SomeInterface<Impl1> {
    @Override
    public Impl1 convert(String param) {
        return null;
    }

    @Override
    public String convert(Impl1 param) {
        return null;
    }
}

但是,您應該問自己,在特殊情況下以這種方式使用泛型是否有意義! SomeInterfaceImpl實例只能分配給SomeInterface<Impl1>類型的字段:

SomeInterface<Impl1> impl1 = new SomeInterfaceImpl();

您不允許將其分配給例如SomeInterface<SomeType>類型的變量:

SomeInterface<SomeType> doesntWork = new SomeInterfaceImpl(); // compile error

這意味着,您的代碼在要使用實現的任何地方都綁定到SomeInterface<Impl1> 如果可以,請繼續使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM