簡體   English   中英

使用泛型進行類型安全

[英]Type safety with generics

我有一堆簡單的界面:

interface County extends Line{}

interface Country<C extends Line> extends LineContainer<C> {}

interface Line {}

interface LineContainer <L extends Line> {
    public List<L> getLines();
}

和服務方法

public static <L extends Line,C extends LineContainer<L>> C getContainer( Class<C> containerType, Class<L> lineType ){
    ...somthing...

調用服務方法

Country<County> c = getContainer( Country.class, County.class );

不會遇到任何錯誤,但是檢查器會說:

類型安全:國家類型的表達式需要未經檢查的轉換才能符合國家

我不明白:通過使用County為L-LineType且以C為L和C的容器來調用服務方法是由Country作為C-Type給出的,因此,我希望類型推斷可以得出結論:對象將被送達。

誰能解釋,為什么我錯了,是否以及如何實現我想要的?

背景:想法是-作為服務的用戶-我可以根據需要自由組合容器和生產線(只要服務提供者可以提供這些服務)

這是因為編譯器不確定Country.class與簽名Country<County>匹配。 Country.class被視為原始類型。

如果您這樣寫:

public static <L extends Line, C extends LineContainer<L>> C getContainer(C container, Class<L> lineType) {
    return null;
}

和:

Country<County> c = getContainer(new Country<County>() {
    @Override
    public List<County> getLines() {
        return null;
    }
}, County.class);

顯然,這可行。

現在想象一下,我將相同的代碼拆分為另一種方式:

    Country foo = new Country<County>() {
        @Override
        public List<County> getLines() {
            return null;
        }
    };
    Country<County> c = getContainer(foo, County.class);

由於原始類型,這將再次在編譯時發出警告。

您的代碼存在的問題是,Country可以具有擴展Line的通用C類型,但是使用您的方法。

getContainer( Country.class, County.class );

此方法不會告訴您該Country.class具有County的C類型。因此,理論上您的返回C將是Country。

不幸的是,除了抑制警告之外,沒有其他真正的解決方案。 或者您不使用Country中的參數並將C固定為County。

public interface Country extends LineContainer<County>

您還可以使用實際對象或供應商等。

我想我解決了...

我的問題的主要錯誤是,我想在容器中定義線元素。 現在,我在Line中定義它所屬的Header。

interface Line<R> {}

然后,我定義了一個LineContainer,它服務於已定義類型的線

interface LineContainer<H, L extends Line<H>> {
    public List<L> getLines();
}

現在,我可以定義一個通用的服務方法(看起來與上面的方法略有不同):

public static <H,L extends Line<H>,C extends LineContainer<H,L>> C getContainer( Class<C> containerType, Class<L> lineType ){
   // ...something...
}

像這樣定義國家和縣:

interface County extends Line<Country>{}
interface Country extends LineContainer<Country,County>{};

我現在可以使用而沒有任何問題:

LineContainer<Country,County> container = getContainer( Country.class, County.class );

LineContainer和Line的另一個示例:

interface Note extends Line<Gamut>{}
interface Gamut extends LineContainer<Gamut,Note>{};
LineContainer<Gamut,Note> container = getContainer( Gamut.class, Note.class );

服務方法必須檢查是否可以提供所需的類型,但是服務的用戶不能合並不兼容的類型:

不允許

LineContainer<Gamut,County> container = getContainer( Gamut.class, County.class );

因為縣不是色域的“線” ...

暫無
暫無

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

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