ジェネリクスを使うと、型によってパラメータ化されたクラスとメソッドを書くことができるため、同じコードが多くの型で動作しながらコンパイル時の型安全性を保つことができます。これはパラメトリック多態性です—「1つの形、あらゆる型」です。
解決する問題
java
();
list.add();
(String) list.get();
ジェネリクスを使うと、型によってパラメータ化されたクラスとメソッドを書くことができるため、同じコードが多くの型で動作しながらコンパイル時の型安全性を保つことができます。これはパラメトリック多態性です—「1つの形、あらゆる型」です。
();
list.add();
(String) list.get();
// With generics: type is known and checked at compile time
List<String> list = new ArrayList<>();
list.add("hi");
String s = list.get(0); // no cast; list.add(42) won't compile
class Box<T> { // T is a type parameter
private T value;
Box(T value) { this.value = value; }
T get() { return value; }
}
Box<Integer> b = new Box<>(42); // T = Integer, checked at compile time
int n = b.get(); // no cast needed
<T extends Comparable<T>> // bounded: T must be comparable
List<? extends Number> // covariance: accept List<Integer>, List<Double>
Javaはジェネリック型を実行時に消去します(型消去)— new T()やinstanceof List<String>はできません。C++テンプレートとC#ジェネリクスは異なる動作をします(単型化/具体化された型)。
ジェネリクスは再利用と安全性を同時に提供します:1つのList<T>がすべての要素型に対応し、コンパイラがランタイムクラッシュになるはずだった型エラーをキャッチします。
安全でないキャストを排除でき、コレクションの基盤です。コードをより再利用可能で、かつ誤用しにくくしています。