Developer

【はじめてのJava】ジェネリックスを使ったクラス定義【コラム】
2022.01.31
Lv1

【はじめてのJava】ジェネリックスを使ったクラス定義【コラム】

はじめてのJava

このシリーズでは、初めてJavaやプログラミングを勉強する方向けに、Javaによるプログラミングの基礎を説明していきます。
目標レベルは、Javaの資格試験の一つである「Oracle Certified Java Programmer, Silver」(通称Java Silver)に合格できる程度の知識の習得です。
はじめてJavaやプログラムに触れる方にもできるだけわかりやすい解説を心がけていきます。


コラム

コラムでは、本編の補足などをしていきます。

この記事では、ジェネリクスを利用したクラスやメソッドの使い方を解説します。
Java Silverではここまで出題されることはありませんが、ジェネリクスについての理解を深めるために見ていきましょう。

目次


ジェネリクスについて復習

まずは、ジェネリクスについて復習をしておきましょう。
ジェネリクスとは、<>を使ってデータ型を指定する仕組みのことです。
ArrayListなどの定義で使用されており、クラスを使用する際に利用するデータ型を指定することができました。。
また、ジェネリクスによってリストなどに想定外の型のデータが格納されることをコンパイルエラーで事前に防ぐことができます。

ジェネリクスに関しての詳しい解説は以下の記事も確認してみてください。
【はじめてのJava】ジェネリックスとラッパークラス【配列とArrayList編】

今までのジェネリクスの解説では、ArrayListを使用してジェネリクスの動作についての解説を行いました。
今回は、ジェネリクスを利用したクラスを自分で定義して利用してみましょう。


ジェネリックスを使ったクラス

ジェネリクスを利用したクラスを定義する際には、クラス定義の後に「<T>」のようにジェネリクスをつけて定義します。
ここで定義した「T」が仮のデータ型を表す文字列になります。
この仮のデータ型をクラス内のフィールドの定義やメソッドの定義で利用することができます。
もし、複数個の仮のデータ型を扱いたい場合には「<A,B>」のようにカンマ区切りで定義することができます。
また、ここで定義する仮のデータ型には以下のいくつかの制約があります。

  • new T()のようにインスタンス化をすることはできない。
  • new T[]のように配列のインスタンス化をすることはできない。
  • T.classの参照はできない。
  • ○○ instanceof Tの演算を行うことはできない。
[使用例]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class SampleClass<T> { //クラス定義の後に「<T>」をつけて定義する!
    private T obj; //フィールドの定義のデータ型にTを利用できる!
     
    public void setObj(T obj){ // objフィールドのSetterを定義。引数のデータ型にTを利用する!
        this.obj = obj;
    }
     
    public T getObj(){ // objフィールドのGetterを定義。戻り値のデータ型にTを利用している!
        return this.obj;
    }
}
 
class ExecuteSample{
    public static void main(String[] args){
         
        SampleClass<String> s1 = new SampleClass<>();
        s1.setObj("Sample");
        System.out.println(s1.getObj());
        // s1はStringクラスを利用してクラスをインスタンス化しているので、フィールドのデータ型はStringになる!
         
        SampleClass<Integer> s2 = new SampleClass<>();
        s2.setObj(123);
        System.out.println(s2.getObj());
        // s2はIntegerクラスを利用してクラスをインスタンス化しているので、フィールドのデータ型はIntegerになる!
         
        //同じクラスを利用しているが、変数やメソッドのデータ型を利用する際に切り替えてインスタンス化できる!
    }
}

ジェネリックスを使ったメソッド

ジェネリクスの仮のデータ型を利用してクラスを定義する方法を紹介しましたが、仮のデータ型はstaticメソッドやstaticイニシャライザでは利用できません
staticメソッドでジェネリクスを利用したい場合、メソッドの定義にジェネリクスを利用します。
メソッドにジェネリクスを利用する場合、メソッド定義の戻り値の型の前に「<T>」のようにジェネリクスをつけて定義します。
ここで定義した仮のデータ型をメソッド内で利用することができます。

[使用例]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class SampleClass{
    //配列をArrayListに変換するメソッド
    public static <T> ArrayList<T> testMethod(T[] list){ //メソッドの戻り値の前に「<T>」を付けて定義する。
        ArrayList<T> arList = new ArrayList<>();
        for(T t:list){
            arList.add(t);
        }
        return arList;
    }
}
 
class ExecuteSample{
    public static void main(String[] args) {
 
        Integer[] numList = {1,2,3,4,5};
        ArrayList<Integer> numArList = SampleClass.testMethod(numList);
 
        String[] strList = {"A","B","C"};
        ArrayList<String> strArList = SampleClass.testMethod(strList);
         
        //メソッドに渡す引数のデータ型が変わっているが、ジェネリクスによって同じメソッドで利用できる!
    }
}

今回は、ジェネリクスの使い方について少し深く見てきました。
うまく使いこなすことで、効率の良いプログラムを書くことができると思いますので、うまく活用してみてください!


初めてのJavaシリーズの目次はこちら


java 11 の練習問題一覧はこちら
はじめてのJavaシリーズの練習問題一覧はこちら