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

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

目次

ジェネリクス

例:Map<String,String> colors = new HashMap<>();
  • ジェネリクスは、<>(山括弧)の中で指定した型をコンパイル時に保証します。
  • 上記の例は、変数colorsのMapのキーとValueの型は、Stringという意味です。String以外の時はコンパイルエラーになります。
  • 指定する型(<String,String>のString)は、基本型ではなく基本型に対応するラッパークラスを指定します。
    Java 変数のデータ型とラッパークラス
  • ジェネリクスは、総称型とも呼ばれます。

型安全

  • 想定と異なる型をセットした場合に、コンパイルエラーにすることにより型のミスを防ぎます。これを型安全といいます。

型引数と型変数

例:public class HashMap<K,V>
  • 上記の例のHashMapの<K,V>を型パラメータ(型引数)と言い、KとVの部分を型変数と言います。
    https://docs.oracle.com/javase/jp/8/docs/api/java/util/HashMap.html
  • 型変数は慣例的に英字1文字で表されます。(KでなくてもKKでもロジックは通ります)
    主な型変数の例
    型変数 意味
    T Type
    K Key
    V Value
    E Element

クラスにジェネリクスを使用

20行目は、クラスにジェネリクスを使用しています。クラスの場合、クラス名(Sample)の後にジェネリクス(<T>)を記述します。
7行目は、ジェネリクスでStringを指定しています。実行できます。20行目にSampleクラスがあります。
11行目は、ジェネリクスでIntegerを指定しています。実行できます。
16行目は、ジェネリクスでStringを指定しています。16行目のコンストラクタの値が数値(123)のためコンパイルエラーになります。

package test1;
 
public class Test1 {
    public static void main(String[] args) {
 
        // <>の中にStringを指定
        Sample<String> s1 = new Sample<>("abc");
        System.out.println(s1.getData1());   //abc
 
        // <>の中にIntegerを指定
        Sample<Integer> s2 = new Sample<>(123);
        System.out.println(s2.getData1());   //123
        
        // <>の中にStringを指定するが
        // コンストラクタの値が数値のためコンパイルエラーになる
//      Sample<String> s3 = new Sample<>(123);
//      System.out.println(s3.get());
    }
}
class Sample<T> {
    T data1;
    
    // コンストラクタ
    public Sample(T data) {
        this.data1 = data;
    }
 
    // メソッド
    public T getData1() {
        return data1;
    }
}

メソッドにジェネリクスを使用

11行目は、メソッドにジェネリクスを使用しています。メソッドの場合、戻り値(T)の前にジェネリクス(<T>)を記述します。
6,8行目は、11行目のメソッドを呼んでいます。

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を使用します。

コード

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

package test1;
 
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");   //
    }
}
class Sample<T extends Number> {
    T data1;
    
    // コンストラクタ
    public Sample(T data) {
        this.data1 = data;
    }
    
    public void setData1(T data1) {
        this.data1 = data1;
    }
}

 

ワイルドカード(?)

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

コード

ワイルドカード(?)のサンプルです。
6,8行目は、ワイルドカード(?)を使用しています。両方実行できます。

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

 

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

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

コード

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

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

package test1;
 
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);
    }
}
class Sample<T> {
    T data1;
    
    // コンストラクタ
    public Sample(T data) {
        this.data1 = data;
    }
}

関連の記事

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

 はまったらエンジニア特化型Q&Aサイト
【teratail(テラテイル)】で質問しましょう!


△上に戻る