ワイルドカード: 柔軟な型

?, extends, super で型の柔軟性を高める。

?
不明な型。柔軟性を提供。
extends
上限境界。読み取り向き。
super
下限境界。書き込み向き。
VIP Pass

ワイルドカードは「VIPパス」。 **?** = フリーパス(誰でもOK) **extends** = 上級パス(VIP以上) **super** = 下級パス(一般以下)

ワイルドカード

?, extends, super
// ワイルドカード: 型の柔軟性
// 非境界ワイルドカード <?>
void printList(List<?> list) {
for (Object obj : list) {
System.out.println(obj);
}
}
// どんな List でも受け取れる
printList(List.of(1, 2, 3));
printList(List.of("a", "b"));
// 上限境界 <? extends T>
void sum(List<? extends Number> numbers) {
double total = 0;
for (Number n : numbers) {
total += n.doubleValue();
}
}
// Number のサブクラスのみ
sum(List.of(1, 2, 3)); // Integer OK
sum(List.of(1.5, 2.5)); // Double OK
// 下限境界 <? super T>
void addIntegers(List<? super Integer> list) {
list.add(1);
list.add(2);
}
// Integer のスーパークラスのみ
List<Number> nums = new ArrayList<>();
addIntegers(nums); // OK
型の柔軟性
List = any type\nList = Integer, Double, ...\nList = Integer, Number, Object
Bad
// ❌ Bad: 型が合わない
List<Object> objects = new ArrayList<>();
List<String> strings = new ArrayList<>();
// objects = strings; // コンパイルエラー
Good
// ✅ Good: ワイルドカードで受け入れ
List<? extends Object> any;
any = strings; // OK
any = integers; // OK

PECS

Producer Extends, Consumer Super
// PECS 原則
// Producer Extends, Consumer Super
// Producer (読み取り専用) - extends を使う
void copy(List<? extends Number> src, ...) {
for (Number n : src) { // 読み取りOK
// ...
}
// src.add(1); // コンパイルエラー!
}
// Consumer (書き込み) - super を使う
void fill(List<? super Integer> dest) {
dest.add(1); // 書き込みOK
dest.add(2);
// Integer i = dest.get(0); // エラー!
}
// 複数の境界
<T extends Comparable<? super T>> void sort(List<T> list) {
// T は Comparable を実装している
}
// Class<T> のワイルドカード
Class<?> clazz = String.class;
Class<? extends Number> numClass = Integer.class;
Tip: PECS: 読むなら extends、書くなら super。

合格ライン

extends と super を使い分けられる
PECS を説明できる

参考リンク

演習課題

課題1: ? extends
読み取り専用のメソッドを ? extends で作成してください。
課題2: ? super
書き込み用のメソッドを ? super で作成してください。

次のステップ