Java ジェネリクスの使い方

2025 年 6 月 6 日 by marukor

ジェネリクスとは

ジェネリクス(Generics)とは、「データ型をパラメータ化して扱う仕組み」です。
クラスやメソッドにおいて、具体的な型を後から指定できるようにすることです。

使い方

ジェネリクスクラス

public class Box<T> {
    private T value;

    public void set(T value) {
        this.value = value;
    }

    public T get() {
        return value;
    }
}

使用例

public class Main {
    public static void main(String[] args) {
        Box<String> stringBox = new Box<>();
        stringBox.set("こんにちは");
        System.out.println(stringBox.get());

        Box<Integer> intBox = new Box<>();
        intBox.set(100);
        System.out.println(intBox.get());
    }
}

Box の T は型のプレースホルダ。使うときに<String> や <Integer> を指定します。

ジェネリクスメソッド

public class Util {
    public static &lt;T&gt; void printTwice(T item) {
        System.out.println(item);
        System.out.println(item);
    }

    public static void main(String[] args) {
        Util.printTwice("Hello");   // String
        Util.printTwice(123);       // Integer
    }
}

メソッドに <T>を定義することで、引数の型に応じて柔軟に対応できます。

応用編

ジェネリクスの**ワイルドカード(<?> , <? extends T> , <? super T>)**

■ ワイルドカードとは?

ワイルドカードは、ジェネリクスの型を柔軟に扱いたいときに使います。
主にコレクション(List, Setなど)を引数に受け取るメソッドで使います。

<?>(無制限ワイルドカード)

意味:どんな型でもOK(型は不明だが何かは入っている)

使用例

public static void printList(List&lt;?&gt; list) {
    for (Object obj : list) {
        System.out.println(obj);
    }
}

public static void main(String[] args) {
    List&lt;String&gt; stringList = List.of("A", "B", "C");
    List&lt;Integer&gt; intList = List.of(1, 2, 3);

    printList(stringList);
    printList(intList);
}

※ ただし、要素の追加はできません(型が不明なため)

<? extends T> (上限ワイルドカード)

意味: T またはそのサブクラス(子クラス)である型に限定

使いどころ: 読み取り専用で使いたいとき(読み込みはOK、書き込みはNG)

使用例

public static void printNumbers(List&lt;? extends Number&gt; list) {
    for (Number num : list) {
        System.out.println(num.doubleValue());
    }
}
List&lt;Integer&gt; ints = List.of(1, 2, 3);
List&lt;Double&gt; doubles = List.of(1.1, 2.2, 3.3);

printNumbers(ints);     // OK
printNumbers(doubles);  // OK

List<? extends Number> なので、Integer や Double も渡せる

ただし、list.add(…) はできません!

<? super T> (下限ワイルドカード)

意味: T またはそのスーパークラス(親クラス)である型に限定

使いどころ: 書き込み(追加)だけしたいときに使う(読み取りは Object 型として扱う)

使用例

public static void addNumbers(List&lt;? super Integer&gt; list) {
    list.add(1);
    list.add(2);
}
List&lt;Object&gt; objs = new ArrayList&lt;&gt;();
addNumbers(objs);  // OK

List&lt;Number&gt; nums = new ArrayList&lt;&gt;();
addNumbers(nums);  // OK

List<? super Integer> なので、Integer の親クラスである Number や Object も許可 追加は Integer 型としてできるが、取り出すときは Object 型としてしか扱えない

まとめ

extends → 「上から読めるけど、下に書き込めない(読み取り専用)」

super → 「下に書き込めるけど、型がわからないから読み取りは制限(追加専用)」

タグ:

TrackBack