javaでコード書いてて、
ここはワイルドカード(?指定)にすべきだよな。
ん?Objectか?あれ?どっちだっけ?
っとよくわからなくなったのでまとめることにしました。
先に結論書くと下記のような感じです。
- ワイルドカード指定だと、それ自体はジェネリクス何指定でも代入できる。
- Object指定だと、Object指定されたものしか代入できない。
- (MapやListは)ワイルドカード指定だと、扱いはほぼ参照専用になる。(例外もある)
functionなどで汎用的に受け取って、中で編集せず参照だけするなら
引数のMapやらListのジェネリクスはワイルドカード使ったほうが便利です。
以下は試してみたコードです。
Map
{
Map<String, ?> wmap = new HashMap<String, String>();//OK
Map<String, Object> omap = new HashMap<String, String>();//コンパイルエラー
}
{
Map<String, ?> wmap = new HashMap<String, Object>();//OK
Map<String, Object> omap = new HashMap<String, Object>();//OK
}
Map<String, ?> wmap = new HashMap<String, Object>();
Map<String, Object> omap = new HashMap<String, Object>();
Map<String, String> smap = new HashMap<String, String>();
Map<String, ?> wmap2 = new HashMap<String, Object>();
Map<String, Object> omap2 = new HashMap<String, Object>();
wmap = smap;//OK
omap = smap;//コンパイルエラー
wmap = wmap2;//OK
omap = wmap2;//コンパイルエラー
wmap = omap2;//OK
omap = omap2;//OK
wmap.put("A", Integer.valueOf(1));//コンパイルエラー
omap.put("A", Integer.valueOf(1));//OK
wmap.put("A", new Object());//コンパイルエラー もちろんObjectでもだめ
wmap.putAll(omap2);//コンパイルエラー
omap.putAll(omap2);//OK
wmap.putAll(wmap2);//コンパイルエラー
omap.putAll(wmap2);//OK
{
Object o1 = wmap.get("A");//OK
Object o2 = omap.get("A");//OK
}
for (Object o : wmap.values()) {//OK
//
}
for (Object o : omap.values()) {//OK
//
}
{
Object o1 = wmap.getOrDefault("A", "S");//コンパイルエラー
Object o2 = omap.getOrDefault("A", "S");//OK
}
{
Object o1 = wmap.computeIfAbsent("A", k -> "S");//コンパイルエラー
Object o2 = omap.computeIfAbsent("A", k -> "S");//OK
}
List
{
List<?> wlist = new ArrayList<String>();//OK
List<Object> olist = new ArrayList<String>();//コンパイルエラー
}
{
List<?> wlist = new ArrayList<Object>();//OK
List<Object> olist = new ArrayList<Object>();//OK
}
List<?> wlist = new ArrayList<Object>();
List<Object> olist = new ArrayList<Object>();
List<String> slist = new ArrayList<String>();
List<?> wlist2 = new ArrayList<Object>();
List<Object> olist2 = new ArrayList<Object>();
wlist = slist;//OK
olist = slist;//コンパイルエラー
wlist = wlist2;//OK
olist = wlist2;//コンパイルエラー
wlist = olist2;//OK
olist = olist2;//OK
wlist.add("A");//コンパイルエラー
olist.add("A");//OK
wlist.add(new Object());//コンパイルエラー もちろんObjectでもだめ
wlist.addAll(olist2);//コンパイルエラー
olist.addAll(olist2);//OK
wlist.addAll(wlist2);//コンパイルエラー
olist.addAll(wlist2);//OK
Object o1 = wlist.get(0);//OK
Object o2 = olist.get(0);//OK
for (Object o : wlist) {//OK
//
}
for (Object o : olist) {//OK
//
}
wlist.remove("A");//OK
olist.remove("A");//OK
wlist.sort((a, b) -> (Integer) a - (Integer) b);//OK
olist.sort((a, b) -> (Integer) a - (Integer) b);//OK