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

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

目次

説明 ジェネリクス(Generics)とは
サンプル ジェネリクスを使用したクラスのサンプル
  ジェネリクスを使用したメソッドのサンプル
  型パラメータに制限をつけるサンプル(extends)
  ワイルドカード(?)
  ワイルドカード(?)に制限をつける(extends/super)

ジェネリクス(Generics)とは

ジェネリクス(Generics)とは、任意のデータ型を指定できる機能のことです。

OracleのJavaのHashMapクラスのページには上記のように<K,V>と書いてあります。
HashMapを使用するときは、KやVにString型やInteger型などのデータ型を指定します。

  • <K,V>を型パラメータといい、KとVは型変数と呼びます。
  • 型変数のKとVに指定した型をコンパイル時に保証します。
    →指定された型以外の値を代入するとコンパイルエラーになります。型安全と呼ばれます。
  • 指定する型は、基本型ではなく参照型を指定します。
  • 型変数は一般的に英字1文字で表します。(キーをKではなくAとしてもロジックは通ります)
  • ジェネリクスは、総称型とも呼ばれます。
主な型変数の例
型変数 意味
T Type、型
K Key、キー
V Value、値
E Element、要素

 

HashMapのサンプル

		Map<Integer,String> c1 = new HashMap<>();
		c1.put(1,"あ");
		//c1.put("A","あ"); //コンパイルエラー

1行目の変数c1のMapのK(key)にあたる型はIntegerで、V(value:値)の型はStringです。
2行目は、指定された型の値をセットしてます。
3行目は、1つめの引数がInteger型ではないのでコンパイルエラーになります。

 

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

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());
    }
}

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

 

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

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;
    }
}

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

 

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

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");   //
    }
}

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

 

ワイルドカード(?)

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

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);
                
    }
}

14行目の引数の値は文字列型です。エラーになりません。
16行目の引数の値は数値型です。エラーになりません。

 

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

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);
    }
}

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

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

関連の記事

Java ArrayListとListの使い方のサンプル
Java HashMapとMapの使い方のサンプル

△上に戻る