Javaのジェネリクスのサンプルです。
目次
- ジェネリクス
- ジェネリクスを使用したクラス
- ジェネリクスを使用したメソッド
- 型パラメータに制限をつける(extends)
- ワイルドカード(?)
- ワイルドカード(?)に制限をつける(extends/super)
ジェネリクス
| 例:public class HashMap<K,V> |
- 上記の例の<K,V>を型パラメータといいます。KとVは型変数です。
- 型変数のKとVには、StringやIntegerなどの参照型を指定できます。
- 型変数のKとVに指定した型をコンパイル時に保証します。
- 型変数は一般的に英字1文字で表します。(キーをKではなくAとしてもロジックは通ります)
主な型変数の例 型変数 意味 T Type、型 K Key、キー V Value、値 E Element、要素
サンプル
型パラメータのサンプルです。
Map<Integer,String> colors1 = new HashMap<>();
colors1.put(1,"あ");
//colors1.put("A","あ"); //コンパイルエラー
- 1行目の変数colors1のMapのキーの型はIntegerで、値の型はStringです。
- 2行目は、指定された型の値をセットしているのでエラーになりません。
- 3行目は、指定された型以外の値を代入しようとしているのでコンパイルエラーになります。
→型安全といいます。 - 指定する型は、基本型ではなく参照型(ラッパークラス)を指定します。
Java 変数のデータ型とラッパークラスとボクシング変換
ジェネリクスを使用したクラス
ジェネリクスを使用したクラスのサンプルです。
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)
型パラメータに制限をつけるサンプルです。
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"); //
}
}
3行目は、extendsを使用して型はNumberクラスまたはNumberのサブクラスという制限をつけています。※NumberクラスのサブクラスにIntegerクラスがあります。
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)
ワイルドカードに制限をつけるサンプルです。
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);
}
}
15行目のジェネリクスは、extendsを使用してIntegerクラスまたはIntegerのサブクラスを指定しています。実行できます。
17行目のジェネリクスの指定は15行目と同じですが、引数が小数点の数値のためコンパイルエラーになります。
19行目は、NumberクラスまたはNumberのサブクラスを指定しています。実行できます。
22行目は、superを使用してIntegerクラスまたはIntegerのスーパークラスを指定しています。そのため引数が小数点の数値ですが実行できます。
24行目は、NumberクラスまたはNumberのスーパークラスを指定しています。実行できます。
※NumberクラスのサブクラスにIntegerクラスがあります。
関連の記事
Java ArrayListの使い方のサンプル
Java LinkedListの使い方のサンプル
Java HashMapの使い方のサンプル
Java LinkedHashMapの使い方のサンプル
Java TreeMapの使い方のサンプル
Java HashSetの使い方のサンプル