Geekroid-ギークロイド(仮)|ITエンジニアの日常をささいな情報で彩るコラム

ITエンジニアの転職

ジェネリックスの定義

ジェネリックスに対応した型を、自分で定義することもできます。以下は、HashMapクラス(java.utilパッケージ)のコードを抜粋したものです。

public class HashMap ~ {
  transient Entry[] table;

  public V put(K key, V value) {
    ...
  }
}

ジェネリック対応のクラスでは、クラス名にも受け取るための型パラメータを指定しなければなりません。HashMapの例であれば「HashMap<K,V>」の部分です。これでK、Vという2つの型(この場合であれば、キーと値の型)を受け取れることを意味します。
型パラメータは、慣例的に大文字一文字で表すのが普通です。E(要素)、K(キー)、V(値)などが良く使われます。
型パラメーターは、以下の場所から参照できます。

・インスタンスメンバー(static修飾子の付かないメンバー)の引数
・インスタンスメンバーの戻り値型
・インスタンスメンバー配下のローカル変数

境界ワイルドカード型

ジェネリックスを利用する際に、#不変#というキーワードを押さえておくことは重要です。たとえば以下のようなコードは、ジェネリックスの世界では不可です。

List list = new ArrayList();

NumberクラスはLongクラスのスーパークラスですが、ジェネリックスではこのような広い型から狭い型への変換も許可しません。型の一致を厳密にチェックするのです(不変の意味です)。
しかし、これは厳密にすぎて使いにくい場合があります。そこでもう少し幅を持った型の指定を可能にしたのが、境界ワイルドカード型です。境界ワイルドカード型では、<? extends E>の形式で型を指定します。これによって、型Eと、その派生クラスを認めるという意味になります。
例えば以下は、ArrayListクラスのaddAllメソッドの例です(addAllはコレクションを配列に追加します)。

public boolean addAll(Collection c) {...}

境界ワイルドカード型を利用することで、たとえばArrayList型のaddAllメソッドに対して、List型の値を渡すことが可能になります。

note

下限境界ワイルドカード
本文で示した境界ワイルドカード型は、指定された型を上限に、その派生クラスを許容することから#上限境界ワイルドカード型#とも呼びます。一方、(それほど利用頻度はおおくないものの)指定された型を下限に、そのスーパークラスを許容する#下限境界ワイルドカード型#もあります。<? super E>のように、superキーワードで表します。

関連ページ
ArrayList

ジェネリックス
ジェネリックスの基本
ジェネリックスの定義
ジェネリックメソッドの定義

Geekroid-ギークロイド(仮)|ITエンジニアの日常をささいな情報で彩るコラム

ITエンジニアの転職