簡體   English   中英

泛型:如何捕獲通配符?

[英]Generics: How to capture a wildcard?

不,這個問題不是關於它們之間的區別嗎? 和T; 這是關於我如何變成<? >參數命名為<T>。 考慮這個示例代碼:

import java.io.Serializable;

class A<T extends Serializable> {
    <S extends Serializable> void bar(S arg) { }
    void bar2(T arg) { }
}

public class B {
    A<? extends Serializable> myA = null;    
    <T extends Serializable> void foo(T arg) {
        myA.bar(arg);
        myA.bar2(arg);
    }
}

我的問題是上面沒有編譯的事實; 對bar2()的調用給了我

The method bar2(capture#2-of ? extends Serializable) in the type
A<capture#2-of ? extends Serializable> is not applicable for the arguments (T)

我猜這個“原因”是myA是<? extends Serializable> ; 但B.foo中的T ......很好,一個名叫T; 而不是通配符?

“修復”這種方法的一種方法是使<T extends Serializable>為B類的類型參數...但這基本上與我對該類的其他用法沖突。 含義:我最終寫下了B及其成員myA,這完全是因為我不想參數化B類。 所以,我開始只使用bar2()方法; 然后稍后添加了bar()......但這並沒有真正幫助。

那么 - 有沒有辦法讓我的班級B在我的示例代碼中使用A.bar2()作為“預期”?

編輯:而且確切地說 - bar()方法對我沒有幫助; 因為那里的“S”......與我在A班中真正使用的“T”不兼容。

你走到了盡頭。

A<? extends Serializable> myA = ...;

所以myAA的未知的東西。 它可以是A<String> ,或A<Integer>A<Banana> 你只是不知道。 讓我們說這是一個A<Banana>

<T extends Serializable> void foo(T arg) {

所以foo()接受任何可序列化的:String,Integer,Banana,Apple,等等。 假設它以Integer作為參數調用。

myA.bar2(arg);

因此,基於上面的假設,雖然myAA<Banana> ,但它會調用bar2()並將Integer作為參數。 編譯器無法接受這一點:它顯然不是類型安全的。 B必須是通用的。

@JBNizet已經解釋了為什么不能這樣做。 這個答案旨在解釋你可能有的選擇(其中一個在你的問題中正確指出,但這不是唯一的選擇)。

使B采用類型參數

class B<T extends Serializable> {

    A<T> myA = null;    

    void foo(T arg) {
        myA.bar(arg);
        myA.bar2(arg);
    }
}

使B從A延伸(如果B通過A的a-a測試)

class B extends A<String> {

    public void foo(String arg) {
        bar2(arg);
        bar(1);
    }
}

兩個選項之間的區別在於:1) barbar2需要傳遞相同的類型,其中2) barbar2可以傳遞不同的類型,因為bar2由為A聲明的類型參數綁定,其中bar是由為方法聲明的類型參數綁定。

暫無
暫無

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

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