Genericsとboxingとoverloadと
本日のICPC練習において、すごく気になることがあったので調べてみた。
Collectionクラス全般に言えることだが、例えばLinkedListにある、removeメソッドというメソッドの型定義は、以下のようになっている。
E remove(int index) リストの指定された位置にある要素を削除します。 boolean remove(Object o) リスト内で最初に検出された、指定要素を削除します。
このメソッドは、オーバーロードされていて、どちらかが静的に決定されて呼び出される。これ自身は別に大したことはないのだけれども、ここにboxingとGenericsが絡むとちょっとややこしくなる。
LinkedListlist = new LinkedList (); list.add(1); list.add(2); list.add(3); System.out.println(list.remove(1)); System.out.println(list.remove(new Integer(1)));
さて、上記のコードはどのように動くのだろうか。
実際にやってみるとわかるのだが、
1 true
となる。この理由は非常に簡単で、まあ要はこのようなケースにおいてはboxingが行われないのだ。
じゃあ、ということで、例えば以下のコード。
LinkedListlist = new LinkedList (); list.add(1); list.add(2); list.add(3); if(list.remove(new Integer(1)) == 1) System.out.println("OK"); if(list.remove(1)) System.out.println("OK");
これはコンパイルエラーになる。本来であれば、boxingが働いて動いて欲しいところだが、残念ながらそうはならない。boxingの動作はかなり怠惰になっていて、さらにこの型チェック機構は決して探索などは行わないらしい。そのほうが分かりやすいと言えばそうなのだけれど・・・