[英]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.