簡體   English   中英

如何強制兩個實例變量具有相同的泛型類型?

[英]How can I force two instance variables to be of the same generic type?

假設我有一個包含泛型類型的兩個實例變量的類,我該如何強制這些類型相同?

我沒有在其他地方找到任何類似的問題(更不用說答案了),這可能是因為我使用了錯誤的術語。 這個問題 ,但我不確定如何將它應用到我的情況。

簡而言之,如何才能使最后一行代碼無法編譯?

class Foo<T> {
    private T value;
}

class Bar {
    private Foo var1;
    private Foo var2;

    public Bar(Foo var1, Foo var2) {
        this.var1 = var1;
        this.var2 = var2;
    }

    public static void main(String[] args) {
        Foo<String> var1 = new Foo<>();
        Foo<Integer> var2 = new Foo<>();
        Bar b = new Bar(var1, var2); // this should not work
    }
}

Make Bar也是通用的:

class Bar<T> {
    private Foo<T> var1;
    private Foo<T> var2;

    public Bar(Foo<T> var1, Foo<T> var2) {
        this.var1 = var1;
        this.var2 = var2;
    }

    public static void main(String[] args) {
        Foo<String> var1 = new Foo<>();
        Foo<Integer> var2 = new Foo<>();
        Bar<String> b = new Bar<>(var1, var2); // this does not work
    }
}

通過使用類級別泛型參數T for Bar您可以為兩個實例變量強制實施相同的類型。

這也消除了@daniu在評論中提到的使用原始類型( 永遠不應該使用 )的警告。


現在,如果您碰巧不使用原始類型希望允許不同類型,則可以使用通配符:

使用上限,只允許鍵入讀取( var1var2將始終生成類型為T的實現):

class Bar<T> {
    private Foo<? extends T> var1;
    private Foo<? extends T> var2;

    public Bar(Foo<? extends T> var1, Foo<? extends T> var2) {
        this.var1 = var1;
        this.var2 = var2;
    }

    public static void main(String[] args) {
        Foo<String> var1 = new Foo<>();
        Foo<Integer> var2 = new Foo<>();
        Bar<Object> b = new Bar<>(var1, var2); // this does now work
    }
}

並且具有較低的有界,只允許類型化寫入( var1var2將始終使用類型T任何實現):

class Bar<T> {
    private Foo<? super T> var1;
    private Foo<? super T> var2;

    public Bar(Foo<? super T> var1, Foo<? super T> var2) {
        this.var1 = var1;
        this.var2 = var2;
    }

    public static void main(String[] args) {
        Foo<Integer> var1 = new Foo<>();
        Foo<Number> var2 = new Foo<>();
        Bar<Integer> b = new Bar<>(var1, var2); // this does now work
    }
}

有關該主題的更多信息,您可以閱讀: 什么是PECS(Producer擴展消費者超級)?

Lino的答案很好。 我想補充一個事實:

如果您不必跟蹤var的類型,但只驗證它們的類型相同,那么您可以將類型參數從Bar類移動到其構造函數:

class Bar {
    // These will always have the same type, but
    // that's not visible here
    private Foo<?> var1;
    private Foo<?> var2;

    // The parameter types of the construct ensures that
    // the vars are always of the same type
    public <T> Bar(Foo<T> var1, Foo<T> var2) {
        this.var1 = var1;
        this.var2 = var2;
    }

    public static void main(String[] args) {
        Foo<String> var1 = new Foo<>();
        Foo<Integer> var2 = new Foo<>();

        Bar b1 = new Bar(var1, var1); // Works fine
        Bar b2 = new Bar(var1, var2); // Compilation error
    }
}

這種技術適用於各種方法。

暫無
暫無

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

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