9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

総称型(ジェネリクス) ワイルドカード指定とObject指定との違い

Posted at

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
9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?