メソッドの戻り値のジェネリクス（List<String>の"String"部分）を動的に変える

メソッドの戻り値のジェネリクス（`List<String>`の`String`部分）を動的に変えてみましょう。


# メリット
どういうメリットがあるかというと、

* 共変戻り値を使っていて、メソッドの戻り値の型が一つに定まらないとき
* 親子関係にあるいろいろな型のオブジェクトが1つのリストに入っていて、そのうち特定の型のオブジェクトだけを抽出して新たなリストを作成して返したいとき（たとえばAndroidアプリの開発で、引数に`Button.class`やら`TextView.class`を渡して、それぞれ`List<Button>`や`List<TextView>`が返ってくるメソッドを作りたいとき）

に役立ちます。

この方法を使えば、
戻り値のジェネリクスが違うだけのメソッドをたくさん作らないですんだり、
返ってきた`List<Foo>`の要素1つ1つに対して型をチェックしたりキャストしたりする手間がなくなります。

それほど頻繁に書きたいコードではありませんが、たまに書きます。

# サンプル

ここでは

* 親クラスである`Super`クラスのオブジェクト
* `Super`を継承した`SubA`クラスのオブジェクト
* `Super`を継承した`SubB`クラスのオブジェクト

が混ざっている配列から、引数で渡された型のオブジェクトだけを抽出してリストを作成し、返すメソッドを考えてみました。
次のサンプルの`getList`メソッドです。

```java
package test;

import java.util.ArrayList;
import java.util.List;

public class GenericsTest {
	public static void main(String[] args) {

		List<Super> superList = getList(Super.class);
		System.out.println("superList.size():" + superList.size());
		for (Super element : superList) {
			System.out.println(element);
		}

		System.out.println("!!!!!!");

		List<SubA> subAList = getList(SubA.class);
		System.out.println("subAList.size():" + subAList.size());
		for (SubA element : subAList) {
			System.out.println(element);
		}

		System.out.println("!!!!!!");

		List<SubB> subBList = getList(SubB.class);
		System.out.println("subBList.size():" + subBList.size());
		for (SubB element : subBList) {
			System.out.println(element);
		}

		System.out.println("!!!!!!");

		List<String> stringList = getList(String.class);
		System.out.println("stringList.size():" + stringList.size());
		for (String element : stringList) {
			System.out.println(element);
		}
	}

	private static <T> List<T> getList(Class<T> clazz) {
		List<T> result = new ArrayList<T>();

		Super[] array = { new Super(), new SubA(), new SubB() };

		for (Super element : array) {
			if (clazz.isAssignableFrom(element.getClass())) {
				result.add(clazz.cast(element));
			}
		}

		return result;
	}

	private static class Super {
		@Override
		public String toString() {
			return "Super";
		}
	}

	private static class SubA extends Super {
		@Override
		public String toString() {
			return "SubA";
		}
	}

	private static class SubB extends Super {
		@Override
		public String toString() {
			return "SubB";
		}
	}
}
```

このコードを実行すると

> superList.size():3
> Super
> SubA
> SubB
> !!!!!!
> subAList.size():1
> SubA
> !!!!!!
> subBList.size():1
> SubB
> !!!!!!
> stringList.size():0

となり、
`Super.class`を引数にすると、`Super`とそのサブクラスのオブジェクトがリストで返ってきて、
`SubA.class`や`SubB.class`を引数にするとそれぞれのオブジェクトだけがリストに入って返ってくることがわかります。
さらに`String.class`を引数にすると、`String`のオブジェクトはもとの配列に入っていなかったので、返ってくるリストには何も入っていません。

# もっと役立てる方法

## 返ってくるリストにサブクラスのオブジェクトを含めないようにする
上のサンプルの

```java
if (clazz.isAssignableFrom(element.getClass()))
```

を

```java
if (clazz == element.getClass())
```

にすれば、返ってくるリストにサブクラスのオブジェクトが入らないようにできます。
具体的には上のコードで言えば、`Super.class`を引数に渡して、返ってくるリストに`SubA`や`SubB`のオブジェクトが入らないようにできます。
Androidでいえば`TextView`のオブジェクトはほしいけれども`Button`のオブジェクトはいらない、というときに役立ちます。
（`Button`は`TextView`のサブクラスなので）

## 引数に受け取るクラスをあるクラスのサブクラスに限定する
[gaka](http://qiita.com/gaka)さんにコメントで教えていただいたので追記します。
[gakaさんのこのコメント](http://qiita.com/arai-wa/items/0cefd78f6e4a5b5128dc#comment-a01631ba1d76f2202f83)のとおりに型引数を`<T extends Super>`というように指定すれば、引数として受け取るクラスの型を指定できます。
こうすれば、たとえば`String.class`を引数として渡そうとすると、`String`は`Super`のサブクラスではないのでコンパイルエラーが発生してくれます。