Java のジェネリックスについて
このページでは、Java のジェネリックスについて詳しく解説します。基本的な概念から、使い方、応用例、制限事項まで幅広く説明します。
ジェネリックスとは
Java のジェネリックスは、型をパラメータとして扱う仕組みを提供します。これにより、型安全性を確保し、コードの再利用性を向上させることができます。
たとえば、リストに異なる型のデータを追加するときに、ジェネリックスを使えば不適切な型のデータを防ぐことができます。
ジェネリックスの利点
- 型安全性の向上: コンパイル時に型チェックを行うことで、実行時のエラーを防ぎます。
- キャストの不要化: 明示的な型キャストが不要になります。
- コードの再利用性: 同じコードを異なる型で簡単に再利用できます。
基本的な構文
ジェネリックスは、クラス、インターフェース、およびメソッドに適用できます。
ジェネリッククラス
class Box {
private T item;
public void setItem(T item) {
this.item = item;
}
public T getItem() {
return item;
}
}
public class Main {
public static void main(String[] args) {
Box stringBox = new Box<>();
stringBox.setItem("Hello");
System.out.println(stringBox.getItem());
Box intBox = new Box<>();
intBox.setItem(123);
System.out.println(intBox.getItem());
}
}
ジェネリックメソッド
public class Utils {
public static void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
public static void main(String[] args) {
String[] stringArray = {"A", "B", "C"};
Integer[] intArray = {1, 2, 3};
printArray(stringArray);
printArray(intArray);
}
}
ワイルドカード
ジェネリックスには「ワイルドカード」という特殊な表現があり、柔軟な型指定が可能です。
ワイルドカードの基本
public void printList(List> list) {
for (Object obj : list) {
System.out.println(obj);
}
}
境界付きワイルドカード
public void addNumbers(List super Integer> list) {
list.add(10);
list.add(20);
}
public void printNumbers(List extends Number> list) {
for (Number num : list) {
System.out.println(num);
}
}
ジェネリックスの制限
- プリミティブ型は使用できない: ジェネリックスはオブジェクト型にのみ適用可能です(ラッパークラスを使用します)。
- 型情報の消去: 実行時には型情報が消去されます(タイプイレージョン)。
- 静的メンバーにジェネリックスは使用不可: 静的メソッドやフィールドに型パラメータを持たせることはできません。
応用例
ジェネリックスタックの実装
class Stack {
private List elements = new ArrayList<>();
public void push(T element) {
elements.add(element);
}
public T pop() {
if (elements.isEmpty()) {
throw new EmptyStackException();
}
return elements.remove(elements.size() - 1);
}
public boolean isEmpty() {
return elements.isEmpty();
}
}
public class Main {
public static void main(String[] args) {
Stack stack = new Stack<>();
stack.push(10);
stack.push(20);
System.out.println(stack.pop());
System.out.println(stack.pop());
}
}
複数の型パラメータ
class Pair {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
}
public class Main {
public static void main(String[] args) {
Pair pair = new Pair<>("Age", 30);
System.out.println("Key: " + pair.getKey());
System.out.println("Value: " + pair.getValue());
}
}