2005.10.31 株式会社四次元データ CTO 畠中晃弘
- 1.1. ジェネリクスとは
- 1.2. ジェネリックなクラス・インタフェースの作成
- 1.3. 型引数
- 1.4. ジェネリクスなクラス・インタフェースの利用
1.3. 型引数
もう少し型引数について詳しく説明します。 型引数はクラス宣言・インタフェース宣言で、クラス名・インタフェース名に続いて指定します。 (正確にはクラス宣言・インタフェース宣言に登場しない、「ジェネリックなメソッド」というものも存在するのですが、後の章で解説します) 型引数は<>で囲み、その中に1つ以上の型変数を定義します。 java.util.Mapのように複数個指定する場合には、コンマ(,)で区切ります。
public interface Map<K, V>{ ...
型変数の命名規則は変数の命名規則と同じですが、英大文字1字が推奨されています。
定義した型変数は、これまでの例に登場したimplements句やextends句、メソッドの引数、返り値だけでなく、インスタンス変数やメソッド内部で用いることもできます。
public class Value<V> { private V value=null; public Value(V value){ this.value=value; } public V getValue(){ return this.value; } public String toString(){ return value.toString(); } }
この例ではインスタンス変数として、型引数で指定された型のオブジェクトvalueを指定しています。 またtoString()メソッド内で、valueのメソッドを呼び出しています。 valueの型はこのクラス作成時には一意に決まっていないのですが、必ずjava.lang.Objectのインスタンスにはなります。 従ってjava.lang.Objectのメソッドだけは、呼び出すことができます。 もし次のように型引数で指定できるクラスを限定した場合には、呼び出すメソッドも増えます。
import java.util.Date; public class Term<S extends Date, E extends Date> { private S start=null; private E end=null; public Term(S start, E end){ this.start=start; this.end=end; } public long calculateSpan(){ return end.getTime()-start.getTime(); } }
extends句を用いて、型引数としてjava.util.Dateのサブクラスしか認めないようにしています。 この場合には、インスタンス変数startもendもjava.util.Dateのインスタンスになります。 従ってjava.util.Dateのメソッドも呼び出すことができます。 型引数で指定できるクラスの限定方法については、後の章で改めて説明します。
1.4. ジェネリクスなクラス・インタフェースの利用
ジェネリックなクラス・インタフェースを利用する場合には、変数宣言やnewでのインスタンス作成時に<>を用いて型引数を指定します。
Value<String> value=new Value<String>("test");
厳密には型引数はメソッド引数と違って必須ではありません。 したがって以下の3通りでもコンパイルエラーとはなりません。
Value value=new Value("test"); Value value=new Value<String>("test"); Value<String> value=new Value("test");
ただプログラム上の解りやすさの観点から言っても、ジェネリクスなクラス・インタフェースでは型引数を指定するのが適切です。
Value<String> value=new Value<String>("test");とするようにしてください。