Going my way

いいなと思ったことをメモしていきます。

【Java】ジェネリックスを使ったサンプルと周辺知識のまとめ


Advertisements


ジェネリックスは何のためにあるの?
コレクション操作において、データ型の不一致をコンパイラに検出させるためです。
コレクションから要素を取得するときは適切なデータ型にキャストする必要があります。
しかし、キャストを指定する際にタイプミスがあっても、コンパイラはそういう問題を検出できません。
ジェネリックスを用いることで、可読性、堅牢性、信頼性を向上させることができます。

ジェネリックスを使わないコードのサンプル

public class NoGenerics {
	public static void main(String[] args){
		List slist = new ArrayList();
		String str = "Hoge";
		slist.add(str);
		String str2 = (String)slist.get(0);
		System.out.println(str2);
	}
}


ジェネリックスを使ったコードのサンプル

public class GenericsSample {
	public static void main(String[] args){
		List<String> list = new ArrayList<String>();
		String st1 = "hoge";
		String st2 = "foo";
		String st3 = "fuga";
		
		Integer i = 555;
		list.add(st1);
		list.add(st2);
		list.add(st3);
		
		//ジェネリックスでStringを指定したコレクションにInteger型をaddしようとすると、
		//コンパイルエラーが発生する。
		//list.add(i);
		
		//拡張for文を使用した取り出し
		for(String st : list){
			System.out.println(st);
		}
		
		System.out.println("--------------------------------");
		//Iteratorを使用した取り出し
		String st = null;
		Iterator<String> itr = list.iterator();
		while(itr.hasNext()){
			st = itr.next();
			System.out.println(st);
		}
	}
}

サンプルの結果は以下の通り。

hoge
foo
fuga
--------------------------------
hoge
foo
fuga


JDK5以降の環境でジェネリックス未使用のコードをコンパイルした場合

C:\temp>javac NoGenerics.java
注:NoGenerics.java の操作は、未チェックまたは安全ではありません。
注:詳細については、-Xlint:unchecked オプションを指定して再コンパイルしてください
。

このように、警告が出力されます。これはただの警告で、コードの実行に影響はありません。

上記でコンパイルが通ったコードはこのようなコードでした。

import java.util.ArrayList;

class NoGenerics {
	public static void main(String[] args){
		ArrayList list = new ArrayList();
		list.add("aaa");
		list.add("bbb");
		list.add(new Integer(1));
		for(Object s : list) {
			System.out.println( ( (String) s).toUpperCase());
		}
	}
}

それで、コンパイルが通ったこのクラスを実行すると・・・

C:\temp>java NoGenerics
AAA
BBB
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer canno
t be cast to java.lang.String
        at NoGenerics.main(NoGenerics.java:9)

このように、キャストのエラーが発生します。
ジェネリックスを使ってコーディングしないとコンパイル時に型のキャストミスによるバグを見逃す可能性が高まります。
ジェネリックスを使用することで、"コンパイル時に"格納したオブジェクトの型をチェックすることができるのです。


型変数名の慣例

型変数名:由来
E:element
K:key
V:value
T:Type


用語の意味
型パラメータ:型パラメータとは、ジェネリックス型の型宣言の中の<>の中の型変数の並びのこと。class HogeのE。
型変数:型変数とは、型パラメータ内に並ぶ変数のこと。ジェネリック方の定義内の型として利用される。
型引数:型引数とは、ジェネリックを使うときに<>に渡す具体的な型のこと。HogeのStringの部分。
パラメータ化された型:型引数を渡された実際に使えるようになった型のこと。Hogeなど。


型パラメータの記述方法
そのクラスとそのサブクラスを許可する
そのクラスとそのスーパークラスを許可する
どのクラスも許可する