簡體   English   中英

Java泛型 - 除了下界之外的通配符的用途?

[英]Java generics - purpose of wildcard except for lower bounds?

使用通配符進行無界或上限泛型的目的是什么? 進一步來說:

為什么我會說public static void foo(List<?> bar)而不是public static <E> void foo(List<E> bar)

為什么我會說public static void foo(List<? extends Baz> bar)而不是public static <E extends Baz> void foo(List<E> bar)

如果您不打算在后面的代碼中引用E ,則無需聲明它。

減少程序員的內存壓力。

如果在運行時決定列表的類型,則需要使用通配符。

如果使用任何命令行參數運行,以下程序將打印List<String> ; 否則會打印List<Number>

public class Test {

    public static List<String> listOfStrings = Arrays.asList("hello", "world");
    public static List<Number> listOfNumbers = Arrays.asList(1, 2, 3, 4.5);

    public static List<?> getListOfUnknown(boolean arg) {
        if(arg) return listOfStrings;
        else return listOfNumbers;
    }

    public static void main(String[] args) {
        System.out.println(getListOfUnknown(args.length > 0));
    }
}

帶通配符的版本是首選。 如果參數的類型為List<?> ,則很明顯將接受任何List 如果接受任何List ,則沒有理由給type參數一個名稱,因此寫<E>只會是混亂的。 另一方面,如果類型參數在簽名中出現兩次,則無法使用通配符。 例如,此簽名需要一個類型參數。

public static <E> List<E> combineLists(List<E> list1, List<E> list2)

實際上在那個例子中,如果參數類型為List<? extends E> List<? extends E> (沒有通配符的唯一方法就是有三個類型參數,一個混亂)。

在Effective Java中,建議即使方法體中需要type參數,也應該更喜歡帶有通配符的簽名版本,並編寫一個私有幫助方法來實現這一點。 例如:

public static void swapFirstAndLast(List<?> list) {
    helper(list);
}

private static <E> void helper(List<E> list) {
    int size = list.size();
    E e = list.get(0);
    list.set(0, list.get(size - 1)); // These lines would not be possible
    list.set(size - 1, e);           // If the type of list were List<?>
}

泛型方法的官方教程已經解釋得很好。

...類型參數T僅使用一次。 返回類型不依賴於類型參數,也不依賴於方法的任何其他參數(在這種情況下,只有一個參數)。 這告訴我們類型參數用於多態; 它唯一的作用是允許在不同的調用站點使用各種實際的參數類型。 如果是這種情況,則應使用通配符。 ...

通用方法允許使用類型參數來表示方法和/或其返回類型的一個或多個參數的類型之間的依賴關系。 如果沒有這種依賴關系,則不應使用通用方法。

暫無
暫無

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

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