【概要】
Autoboxing は便利な機能である。
だが、実際の挙動を表すコードが隠れてしまう分、意外なところで問題が発生したりして注意が必要である。例えば私が最近見た例だと、次のようなものがある。

【詳細】
import java.util.*;

public class DataContainer {
  private final Map dataMap = new HashMap();

  public void put(String key, Object value) {
    dataMap.put(key, value);
  }

  public boolean getBooleanValue(String key) {
    return (Boolean) dataMap.get(key);
  }

  public int getIntegerValue(String key) {
    return (Integer) dataMap.get(key);
  }

  public static void main(String[] args) {
    DataContainer dataContainer = new DataContainer();
    dataContainer.put("key1", Boolean.valueOf(true));
    dataContainer.put("key2", Integer.valueOf(5));

    // 登録されているデータを取得
    boolean value1 = dataContainer.getBooleanValue("key1");
    int value2 = dataContainer.getIntegerValue("key2");

    // 登録されていないデータを取得
    int value3 = dataContainer.getIntegerValue("key3"); // NullPointerException
  }
}
このソースで定義されている DataContainer はもともとは JDK1.4 用に作られていたもので、オリジナルのソースではシグニチャがプリミティブタイプではなく、Integer や Boolean になっていた。

このソースを担当者がリファクタリングしていく課程で、開発環境が JDK 5.0 に移行したため、Autoboxing に対応させて上のように書き換えたものである。

Unboxing が使われているため、このソースだと getBoolean() の中で Boolean#booleanValue() が呼び出されていることや、getIntegerValue() の中で Integer#intValue() が呼び出されていることに気づきにくくなってしまっている。

この手の「隠された挙動」による例外の発生には要注意である。