→ ssccg: 在你舉的method參數,只用在一個地方的情況下,兩個一樣 08/29 13:14
→ ssccg: methods.html 官方文件是建議在這個情況下用wildcard 08/29 13:16
→ ssccg: wildcard才能做到的如你說的就是下限(super),另外就是不需 08/29 13:19
自己在寫時都沒有限定參數邊界過
一直都是用 public <E> void process(List<E> datas)
最近看了某些 API 的 source,突然才想到一直沒搞懂泛性這塊
查了一些資料,看到 covariant、contravariant、invariant
現在反而更混亂,有一種若要直接下結論的話
反正就是要限定參數邊界時,不管上限或下限,用 wildcard 就對了
→ ssccg: 要type parameter可以直接用在field、local variable 08/29 13:19
→ ssccg: 而generic的type parameter可以用在多個參數,可有多個上限 08/29 13:30
請問不需要 type parameter 可以直接用在 field 是什麼意思
泛型可以用在 field,但這句話不是指 wildcard 可以用在 field 吧?
感謝說明
→ ssccg: wildcard可以用在field沒錯啊,上面的網頁最下面也有範例 08/30 02:00
→ ssccg: generic要用在field,必須要class有type parameter 08/30 02:03
→ ssccg: 而wildcard可直接用像 class A {List<? extends B> list;} 08/30 02:05
→ ssccg: 如果不是真的需要generic class,這時wildcard就比較適合 08/30 02:06
→ ssccg: 而method部分也不是wildcard就對了,上面也說了限制有多個 08/30 02:09
→ ssccg: 或多個參數時就只能用generic 08/30 02:12
→ ssccg: 其實兩個語意就是有差,wildcard是未知,頂多加上一些限制 08/30 02:14
→ ssccg: generic是寫其他程式用到再決定,但用到後就是確定的 08/30 02:18
→ ssccg: 更正一下最後兩個generic → type parameter 08/30 02:55
感謝 ssccg 大的說明
如果先不論語法,編譯檢查等
單純只論為什麼要用 wildcard
以JDK 的 List 介面來說
public interface List<E> extends Collection<E>
有一個方法是 boolean containsAll(Collection<?> c);
如果是這樣定義的
boolean containsAll(Collection<E> c);
那當我們建立 List<String> strs = Arrays.asList("1", "2");
那這個 strs 的 containsAll 方法,只能用來比較 String 集合了
反之因為使用 ? 定義
boolean containsAll(Collection<?> c); 這樣定義
所以 strs 還是可以用來比對各種型態的集合
我想一開始會不懂 <T> 和 ? 的差別
應該是在 "定義" 和 "使用" 沒搞清楚差別
1. ? 必須用在已經使用在 <T> 定義好的類別之,只是它可是任意型態
2. 在 generics class,<T> 和 ? 的使用就會有如上面 containsAll 的差別
但是在泛型方法中,應該就沒有泛型類別上的限制
public class XyzUtil {
public static <T> void process(T t) {
System.out.println(t);
}
}
在使用 process(T t) 時,每次呼叫方法時,才決定參數的型態
所以這時候使用 <T> 和 ? 的行為就是一樣的
也就是此時的 T 也相當於任意型態,不知這樣理解對嗎
因為一直以來我都只有使用 generics method
所以覺得 <T> 和 ? 不是一樣的東西嗎
除了在限制參數邊界時,? 可以使用 super
只是我會用 <T extends Number> 之類別,卻還沒用過 super
所以也就一直沒研究 <T> 和 ? 的差別
※ 編輯: jtorngl (114.43.70.113 臺灣), 08/30/2020 16:48:07
→ tw11509: Producer Extends, Consumer Super 關鍵字,可以參考一 08/31 11:54
→ tw11509: 下 08/31 11:54
→ tw11509: 對我來說,通常不用去管泛型類別時,我會選擇用wildcard 08/31 12:48
→ tw11509: ,例如:Collections#swap,交換List中的元素根本不需要 08/31 12:48
→ tw11509: 知道裡面裝了什麼類別的元素 08/31 12:48
感謝說明,也有在看 <? exends T> 和 <? super T>
原本只是以為單純的設定型別的上下界
但是還有 set 和 get 使用上的限制,而且有點不好懂
我才知道原來自己對泛型的理解還很淺
像是
Number[] nums = new Integer[3]; // ok
List<Number> nums = new ArrayList<Integer>(); // compile error
語法的限制,或是編譯器的限制等等的細節
都沒去理解,還有得學
※ 編輯: jtorngl (111.249.70.26 臺灣), 08/31/2020 13:08:52