[問題] 請問泛型的問題
請問 Collection 不支援 covariance (還是該說泛型不支援 covariance)
所以 summary 只能傳入 List<Number> 的物件
而不能傳入 List<Integer>、List<Double>, ...
public double summary(List<Number> nums) {
double total = 0;
for (Number num : nums) {
total += num.doubleValue();
}
return total;
}
為了讓這段程式能達到類似 covariance 機制
所以會使用 wildcard
public double wildcardSummary(List<? extends Number> nums) {
double total = 0;
for (Number num : nums) {
total += num.doubleValue();
}
return total;
}
不過泛型使用 extends 一樣可以做到不是嗎
private <E extends Number> double genericsSummary(List<E> nums) {
double total = 0;
for (Number num : nums) {
total += num.doubleValue();
}
return total;
}
目前能想到的只有,wildcard 有 super 來達到 contravariance
但是泛型只支援 extends 而沒有支援 super
那如果沒有要 contravariance 的效果
有什麼情況是 wildcard 才能做到,而泛型還是不能編譯的?
目前看一些文章,在方法的參數,要限制參數型態邊界時
幾乎都是使用 List<? extends Number>
好像比較少看到 <E extends Number> ... List<E>
看了一下 JDK 的 List interface
boolean addAll(Collection<? extends E> c);
是因為限制的參數型態都是動態,才只能用 wildcard 嗎?
補充一下,問這個問題主要是,目前開始接觸 sonarcube 這類工具
對於程式會有很多規範,雖然目前還沒去看是否有泛型語法的 issue
只是想先問一下,實際開發時,是否在需要限制參數邊界時
一律使用 wildcard,而不要用泛型宣告
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.43.70.113 (臺灣)
※ 文章網址: https://www.ptt.cc/bbs/java/M.1598675517.A.17E.html
※ 編輯: jtorngl (114.43.70.113 臺灣), 08/29/2020 12:36:01
→
08/29 13:14,
4年前
, 1F
08/29 13:14, 1F
→
08/29 13:15,
4年前
, 2F
08/29 13:15, 2F
→
08/29 13:16,
4年前
, 3F
08/29 13:16, 3F
→
08/29 13:19,
4年前
, 4F
08/29 13:19, 4F
自己在寫時都沒有限定參數邊界過
一直都是用 public <E> void process(List<E> datas)
最近看了某些 API 的 source,突然才想到一直沒搞懂泛性這塊
查了一些資料,看到 covariant、contravariant、invariant
現在反而更混亂,有一種若要直接下結論的話
反正就是要限定參數邊界時,不管上限或下限,用 wildcard 就對了
→
08/29 13:19,
4年前
, 5F
08/29 13:19, 5F
→
08/29 13:30,
4年前
, 6F
08/29 13:30, 6F
請問不需要 type parameter 可以直接用在 field 是什麼意思
泛型可以用在 field,但這句話不是指 wildcard 可以用在 field 吧?
感謝說明
→
08/30 02:00,
4年前
, 7F
08/30 02:00, 7F
→
08/30 02:03,
4年前
, 8F
08/30 02:03, 8F
→
08/30 02:05,
4年前
, 9F
08/30 02:05, 9F
→
08/30 02:06,
4年前
, 10F
08/30 02:06, 10F
→
08/30 02:09,
4年前
, 11F
08/30 02:09, 11F
→
08/30 02:12,
4年前
, 12F
08/30 02:12, 12F
→
08/30 02:14,
4年前
, 13F
08/30 02:14, 13F
→
08/30 02:18,
4年前
, 14F
08/30 02:18, 14F
→
08/30 02:55,
4年前
, 15F
08/30 02:55, 15F
感謝 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
→
08/31 11:54,
4年前
, 16F
08/31 11:54, 16F
→
08/31 11:54,
4年前
, 17F
08/31 11:54, 17F
→
08/31 12:48,
4年前
, 18F
08/31 12:48, 18F
→
08/31 12:48,
4年前
, 19F
08/31 12:48, 19F
→
08/31 12:48,
4年前
, 20F
08/31 12:48, 20F
感謝說明,也有在看 <? 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
討論串 (同標題文章)
java 近期熱門文章
PTT數位生活區 即時熱門文章