Javaジェネリクス(Generics)
Genericsとは?
ジェネリクス(Generics)はJava 5で導入されたもので、データ型を一般化する(Generalize) という意味である。
ジェネリクスは、クラスまたはメソッドで使用するデータ型をあらかじめ指定する方法である。
ジェネリクスを使用すると、データ型の不一致問題をコンパイル過程で防ぐことができる。
また、ジェネリクスを使用すると型キャストを行う必要がなくなるため、プログラムの性能が向上する。
BadGenericsSample.java
package com.devkuma.basic.generics;
import java.util.ArrayList;
import java.util.List;
public class BadGenericsSample {
public static void main(String[] args) {
List arrayList = new ArrayList();
arrayList.add("test");
String test = arrayList.get(0); // error
}
}
上の例のように、ジェネリクスでデータ型を指定せずにデータを保存すると、保存されるデータはObject型として保存される。
そのため、取り出すときには必ず型変換を行う必要がある。
GoodGenericsSample.java
import java.util.ArrayList;
import java.util.List;
public class GoodGenericsSample {
public static void main(String[] args) {
List<String> arrayList = new ArrayList();
arrayList.add("test");
String test = arrayList.get(0); // ok
}
}
ジェネリクスでデータ型をあらかじめ指定すると、保存されるデータが指定された型として保存されるため、データを取り出すときに型変換を行わなくてもよい。
ジェネリクスの使い方
ジェネリクスは以下のように宣言する。
public class クラス名<T>
public interface インターフェース名<E>
<>括弧の中に入れる文字に決まった規則はないが、一般的には大文字のアルファベットで表す。
クラスでジェネリクスを使用
以下はクラスでジェネリクスを使用した例である。
package com.devkuma.basic.generics.ex2;
public class GenericsSampleClass<T> {
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
上のように作成したクラスは、インスタンスを生成して使用するときにデータ型を指定して使用する。
package com.devkuma.basic.generics.ex2;
public class GenericsSample {
public static void main(String[] args) {
GenericsSampleClass<String> classSample = new GenericsSampleClass();
classSample.setT("SetItem");
String getItem = classSample.getT();
}
}
インターフェースでジェネリクスを使用
以下はインターフェースでジェネリクスを使用した例である。
package com.devkuma.basic.generics.ex3;
public interface GenericInterfaceSample<T> {
T testMethod(T t);
}
上のように作成されたインターフェースは、実装クラスでデータ型を指定できる。
package com.devkuma.basic.generics.ex3;
public class GenericInterfaceSampleImpl implements GenericInterfaceSample<String> {
@Override
public String testMethod(String t) {
return null;
}
}
ジェネリクスの範囲指定
ジェネリクスで指定するデータ型の範囲も、継承を利用すると制限できる。
package com.devkuma.basic.generics.ex4;
public class GenericClassSample<T extends Number>{
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
上のように作成されたクラスは、ジェネリクスでデータ型を指定するとき、Numberクラスを継承するクラスだけを指定できる。
package com.devkuma.basic.generics.ex4;
public class GenericSample {
public static void main(String[] args) {
GenericClassSample<String> classSample = new GenericClassSample(); // error
classSample.setT("SetItem");
String getItem = classSample.getT();
}
}
上のようにジェネリクスでデータ型をStringとして指定しているが、StringはNumberクラスの下位クラスではないため、コンパイルエラーが発生する。