ラムダ式の勉強をしていたらConsumer<T>のようなインターフェースを見かけました。
List<Stting> なんかは見たことあったけれど、<T>って何?となったので調べてみました。
総称型 (Generic /ジェネリック type)とは
総称型(Generic /ジェネリック type)とは、端的に言えば「<>」のを使った機能のことです。
「<>」を使用してクラス、インターフェース、メソッドなどにString型やInteger型などの型を定義することを可能にしているものです。
型パラメータとは
<T>が総称型の一種であることがわかりましたが<T>のTがなんなのか掘り下げていきます。
インターフェースを作成する際など具体的なデータ型がまだ決まっていない時があります。
そんな時に型パラメータ(Type Parameter)が使用されます。型パラメータは<T>のように書き、実際に使用する際に<String>などに代入されて使用されます。
型パラメータは型変数や仮型パラメータなどとも呼ばれているようです。
Listのインターフェースを確認してみると以下のように定義されています。
public interface List<E>
型パラメータとしてEが使われてるのがわかります。
実際にListを使用する際は以下のように変化します。
List<String> obj = new ArrayList<String>();
例でStringの型を指定しています。このStringは実型パラメータ (actual type parameter)と呼ばれたりもします。
型パラメータの英語の意味
総称型の型パラメータには慣例としてクラスやインターフェースの名前とすぐに見分けがつくように英語の大文字1文字が使われています。
一般的に使用されている型パラメータ名を紹介します。
- E – Element(要素)(Javaのコレクション フレームワークで多用されている)
- K – Key(キー)
- N – Number(数値)
- T – Type(タイプ)
- V – Value(値)
- S,U,V etc. – 2番目、3番目、4番目… types
Oracleのサイトでは上記が紹介されていましたが、この他にもR – Return (戻す型)、P – Parameter(パラメータ) が使われているのを見かけます。
型パラメータを複数記述する書き方
型パラメータは複数記述することが可能です。
class クラス名 <E, S, …>
カンマ区切りで複数記述することができます。
総称型の書き方の種類
総称型には以下のような書き方があります。
用語 | 例 | 説明 |
---|---|---|
ジェネリック型 (generic type) | List<E> | 型パラメータが使用されている |
パラメータ化された型 (parameterized type) | List<String> | 実型パラメータが使用されている |
境界型パラメータ (bounded type parameter) | <E extends Number> | 適用される型を継承したクラスで使用されている型に制限している |
多数の境界 (multiple bounds) | <E extends Class1 & Class2> | 上記の状態から継承するクラスを複数記述している |
非境界ワイルドカード型 (unbounded wildcard type) | List<?> | なんらかの型を持つ |
上限境界ワイルドカード型 (bounded wildcard type) | List<? extends Number> | 指定した型と同じ、またはその型を継承するサブクラス(サブインターフェース)を表す |
下限境界ワイルドカード | List<? super Integer> | 指定した型と同じ、またはその型のスーパークラスを表す |
「?」=「ワイルドカード」が出てくるとより難しく感じますが、詳しくは長くなるのでここでは省略します。ググってみてください。いつか別記事でまとめたいと思います。
おわり
<E>とか見た時はまったく意味がわからず今はまだ関係ないと理解しようとも思っていませんでしたが、知らなかっただけでジェネリックの機能を使っていたことに驚きました。
ジェネリックなのかジェネリクスなのか、正しい使い分け方がわからなかったので間違ってたらすみません。
参考
・https://so-zou.jp/ジェネリック (generic) : 総称
・Java ジェネリクスのポイント
・シグネチャに、T とか、K とか書いてあると API そっ閉じしちゃうジェネリクス フォビア向けに、Java の総称型を説明してみた