Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
ジェネリクス(<T>)
型パラメータを使って「どんな型でも動くクラスやメソッド」を定義する仕組みです。コレクションクラス(List<T> など)がその代表例で、コンパイル時に型の安全性を保証します(Java 5以降)。
構文
// ジェネリクスクラスの定義です。
class Box<T> {
private T value;
Box(T value) { this.value = value; }
T get() { return value; }
}
// ジェネリクスメソッドの定義です。
static <T> T firstElement(List<T> list) {
return list.get(0);
}
// 型パラメータに上限境界を設定します(Tは Number のサブタイプ)。
class NumericBox<T extends Number> {
T value;
double doubleValue() { return value.doubleValue(); }
}
// ワイルドカード:不明な型を表します。
void printList(List<?> list) { /* 任意の型のListを受け取れます */ }
// 上限境界ワイルドカード:Numberのサブタイプを受け取ります。
double sumList(List<? extends Number> list) {
return list.stream().mapToDouble(Number::doubleValue).sum();
}
// 下限境界ワイルドカード:Integerのスーパータイプを受け取ります。
void addNumbers(List<? super Integer> list) {
list.add(42);
}
主な記法一覧
| 記法 | 概要 |
|---|---|
| <T> | 型パラメータ。任意の型を表します。慣例として T(Type)・E(Element)・K(Key)・V(Value)が使われます。 |
| <T extends Number> | 型パラメータに上限を設けます。T は Number またはそのサブクラスに限定されます。 |
| <?> | ワイルドカード。不明な型を表します。読み取り専用の処理に使います。 |
| <? extends T> | 上限境界ワイルドカード。T のサブタイプを受け取ります(出力用)。 |
| <? super T> | 下限境界ワイルドカード。T のスーパータイプを受け取ります(入力用)。 |
サンプルコード
import java.util.*;
// ジェネリクスクラスを使用します。
Box<String> strBox = new Box<>("Hello");
Box<Integer> intBox = new Box<>(42);
System.out.println(strBox.get()); // 『Hello』と出力されます。
System.out.println(intBox.get()); // 『42』と出力されます。
// ジェネリクスメソッドを使用します。
List<String> names = List.of("Alice", "Bob", "Carol");
System.out.println(firstElement(names)); // 『Alice』と出力されます。
// 型境界でNumberのサブクラスに限定します。
NumericBox<Integer> nb = new NumericBox<>();
nb.value = 100;
System.out.println(nb.doubleValue()); // 『100.0』と出力されます。
// ワイルドカードで複数の型のListを処理します。
List<Integer> ints = List.of(1, 2, 3, 4, 5);
List<Double> dbls = List.of(1.5, 2.5, 3.5);
System.out.println(sumList(ints)); // 『15.0』と出力されます。
System.out.println(sumList(dbls)); // 『7.5』と出力されます。
概要
ジェネリクスを使うことで、Object 型を使ったキャストなしに型安全なコードが書けます。List<String> には String しか追加できないため、実行時の ClassCastException を防げます。
Javaのジェネリクスは「型消去(Type Erasure)」という仕組みで実現されており、コンパイル後には型情報が消えて Object に置き換えられます。そのため、実行時にジェネリクスの型パラメータを instanceof で確認したり、new T() でインスタンス生成したりすることはできません。
ラムダ式とジェネリクスの組み合わせについては『Predicate / Function / Consumer / Supplier』を、コレクションクラスの活用については対応するページを参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。