ワイルドカード: 柔軟な型
?, extends, 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 OKsum(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; // OKany = integers; // OKPECS
// 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 で作成してください。