ジェネリクスむずかしい
ちょっと悩んだメモ。
あくまでイメージコード
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は、引数の?と戻り値の?が一緒の型であるって定義はしていない・・・から?