ジェネリクスむずかしい

ちょっと悩んだメモ。

あくまでイメージコード

public void hoge1(List<? extends Serializable> list) {
	// List<List<? extends Serializable> では受け取れない
	List<?> list2 = foo(list);
}

public void hoge2(List<String> list) {
	List<List<String>> list2 = foo(list);
}

public <T extends Serializable> void hoge3(List<T> list) {
	List<List<T>> foo = foo(list);
}

public <T> List<List<T>> foo(List<T> list) {
	List<List<T>> result = new ArrayList<>();
	result.add(list);
	return result;
}

何を悩んだのかというと

インタフェースの定義としてどちらにしておくべきなのか?

public interface Foo {
	void hoge(List<? extends Serializable> list);
	<T extends Serializable> void hoge(List<T> list);
}

使う側からすれば変わらないような気がするけど・・・

これだと使う側に影響はある

なので意味はある。

public interface Foo {
	List<? extends Serializable> bar1(List<? extends Serializable> list);
	<T extends Serializable> List<T> bar2(List<T> list);
}
public void use() {
	Foo foo = ・・・
	List<String> list = new ArrayList<>();
	
	// List<String>で受けられない
	List<? extends Serializable> bar1 = foo.bar1(list);
	// List<String>で受けられる
	List<String> bar2 = foo.bar2(list);
}

bar1は、引数の?と戻り値の?が一緒の型であるって定義はしていない・・・から?