Java ジェネリクスのサンプル

Javaのジェネリクスのサンプルです。

目次

ジェネリクスを使用したクラス

例:public class HashMap<K,V>
  • 上記の例の<K,V>を型パラメータ(型引数)といいます。
  • 型パラメータには、StringやIntegerなど任意の参照型を指定できます。
    →型パラメータで指定した型をコンパイル時に保証します。
  • KとV自体は型変数と言います。
  • 型変数は一般的に英字1文字で表します。(KでなくてもAでもロジックは通ります)
    主な型変数の例
    型変数 意味
    T Type 型
    K Key キー
    V Value 値
    E Element 要素
  • 以下は、OracleのJavaのHashMapのリンクです。クラス名のところにHashMap<K,V>と書いてあることが確認できます。
    https://docs.oracle.com/javase/jp/8/docs/api/java/util/HashMap.html

ジェネリクスがあるクラスを使用する

例1:Map<Integer,String> colors1 = new HashMap<>();
例2:Map<String,String> colors2 = new HashMap<>();
  • 型パラメータに任意の参照型を指定できます。
  • 上記の例1の意味は、
    変数colors1のMapのキーの型はIntegerで、値の型はStringです。
  • 上記の例2の意味は、
    変数colors2のMapのキーの型はStringで、値の型はStringです。
  • 指定された型以外の代入は、コンパイルエラーになります。
    →型安全といいます。
  • 指定する型は、基本型ではなくラッパークラス、参照型を指定します。
    Java 変数のデータ型とラッパークラス
  • ジェネリクスは、総称型とも呼ばれます。

コード1 (ジェネリクスを使用したクラス)

ジェネリクスを使用したクラスのサンプルです。

3行目は、クラス名(Sample)の後にジェネリクス(<T>)を記述しています。
18行目は、ジェネリクスでString型を指定しています。実行できます。
21行目は、ジェネリクスでInteger型を指定しています。実行できます。
24行目は、ジェネリクスでString型を指定していますがコンストラクタの値が数値(123)のためコンパイルエラーになります。

package test1;
 
class Sample<T> {
    T data1;
    
    // コンストラクタ
    public Sample(T data) {
        this.data1 = data;
    }
    // メソッド
    public T getData1() {
        return data1;
    }
}
public class Test1 {
    public static void main(String[] args) {
 
        Sample<String> s1 = new Sample<>("abc");
        System.out.println(s1.getData1());   //abc
 
        Sample<Integer> s2 = new Sample<>(123);
        System.out.println(s2.getData1());   //123
        
//      Sample<String> s3 = new Sample<>(123);
//      System.out.println(s3.get());
    }
}

コード2 (ジェネリクスを使用したメソッド)

ジェネリクスを使用したメソッドのサンプルです。

11行目は、メソッドにジェネリクスを使用しています。メソッドの場合、戻り値(T)の前にジェネリクス(<T>)を記述します。
6行目は、引数にString型を指定しています。実行できます。
8行目は、引数にInteger型を指定しています。実行できます。

package test1;
 
public class Test1 {
    public static void main(String[] args) {
 
        System.out.println(getTest1("abc")); //abc
 
        System.out.println(getTest1(123)); //123
        
    }
    private static <T> T getTest1(T a){
        return a;
    }
}

 

型パラメータに制限をつける(extends)

型パラメータに制限をつけることができます。
extendsを使用します。

コード

3行目は、extendsを使用して型はNumberクラスまたはNumberのサブクラスという制限をつけています。※NumberクラスのサブクラスにIntegerクラスがあります。
18行目と22行目の引数の値は数値のためエラーになりません。
20行目と24行目の引数の値は文字列型のためコンパイルエラーになります。

package test1;

class Sample<T extends Number> {
    T data1;
    
    // コンストラクタ
    public Sample(T data) {
        this.data1 = data;
    }
    
    public void setData1(T data1) {
        this.data1 = data1;
    }
}
public class Test1 {
    public static void main(String[] args) {
  
        Sample<Integer> s1 = new Sample<>(123);

//        Sample<Integer> s2 = new Sample<>("123");
        
        s1.setData1(456);   //
        
//        s2.setData1("456");   //
    }
}

 

ワイルドカード(?)

ワイルドカード(?)は、コンパイル時に型が不明であることを意味します。何の型かは、実行するときわかります。ジェネリクスと併用できることが利点です。

コード

ワイルドカード(?)のサンプルです。
14行目の引数の値は文字列型です。エラーになりません。
16行目の引数の値は数値型です。エラーになりません。

package test1;

class Sample<T> {
    T data1;
    
    // コンストラクタ
    public Sample(T data) {
        this.data1 = data;
    }
}
public class Test1 {
    public static void main(String[] args) {
 
        Sample<?> s1 = new Sample<>("abc");
 
        Sample<?> s2 = new Sample<>(123);
                
    }
}

 

ワイルドカードに制限をつける(extends/super)

ワイルドカードに制限をつけることができます。
extendsまたはsuperを使用します。

コード

15行目のジェネリクスは、extendsを使用してIntegerクラスまたはIntegerのサブクラスを指定しています。実行できます。
17行目のジェネリクスの指定は15行目と同じですが、引数が小数点の数値のためコンパイルエラーになります。
19行目は、NumberクラスまたはNumberのサブクラスを指定しています。実行できます。

22行目は、superを使用してIntegerクラスまたはIntegerのスーパークラスを指定しています。そのため引数が小数点の数値ですが実行できます。
24行目は、NumberクラスまたはNumberのスーパークラスを指定しています。実行できます。
※NumberクラスのサブクラスにIntegerクラスがあります。

package test1;

class Sample<T> {
    T data1;
    
    // コンストラクタ
    public Sample(T data) {
        this.data1 = data;
    }
}
public class Test1 {
    public static void main(String[] args) {

        // extends
        Sample<? extends Integer> s1 = new Sample<>(123);
        
//        Sample<? extends Integer> s2 = new Sample<>(123.1);
        
        Sample<? extends Number> s3 = new Sample<>(123.1);
        
        // super  
        Sample<? super Integer> s4 = new Sample<>(123.1);
      
        Sample<? super Number> s5 = new Sample<>(123.1);
    }
}

関連の記事

Java if文のサンプル
Java for文とbreakとcontinueのサンプル
Java switch文のサンプル
Java while文とdo...while文のサンプル
Java 変数のデータ型とラッパークラス
Java static初期化ブロックと初期化ブロックのサンプル
Java staticインポートのサンプル
Java final修飾子のサンプル
Java 標準アノテーションのサンプル
Java 列挙型(enum型)のサンプル
Java 可変長引数のメソッドのサンプル



△上に戻る