JPCERT コーディネーションセンター

EXP04-J. オートボクシングされた値が想定した型を持つようにする

ボクシングは、プリミティブ型の値を対応する参照型の値に変換する。int から Integer への自動変換はこの一例である[JLS 2005]。MapList などのコレクションクラスのように、引数にオブジェクトが要求される場合、この変換は便利である。その他、プリミティブ型ではなくオブジェクト参照を引数とするメソッドにもボクシング変換は使用される。ラッパー型(クラス)への自動変換機能によって、コードもより簡潔になる。

ボクシングを引き起こす参照型が以下のような数値ラッパー型の一つであれば、式は想定通りの型にオートボクシングされる (すなわちBooleanByteCharacterShortIntegerLongFloatDouble のいずれか)。しかし、ボクシングを引き起こす参照型が抽象クラス(たとえばNumberObject)であり、プリミティブ数値型を含む式の値が変換されるとき、予期せぬ結果を生む可能性がある。後者の場合、ボクシングの結果となるラッパー型は、式の評価に関わる数値格上げ規則に基づいて决まる。抽象クラスの引数にプリミティブ算術型の(値を持つ)式を渡すときには、ボクシングが行われる前に想定するプリミティブ数値型にキャストしなければならない(意図した型が式の結果の型と同じでない限り)。

違反コード

以下の違反コード例は、HashSet のサイズとしてプログラマが意図した 1 ではなく 100 を出力する。i-1short 型と int 型からなる式であり、その結果の値は Short オブジェクトではなく Integer オブジェクトにボクシングされる。HashSet に含まれているのは Short オブジェクトだけなのに、このコードでは Integer オブジェクトを削除しようとしているため、remove() は何もしない。

public class ShortSet {
  public static void main(String[] args) {
    HashSet<Short> s = new HashSet<Short>();
      for (short i = 0; i < 100; i++) {
        s.add(i);
        s.remove(i - 1);  // Integer を削除しようとしている
      }
    System.out.println(s.size());
  }
}

HashSet には Short 型の値のみを追加できることが、Java 言語の型検査で保証されている。一方、Collections<E>.remove() の引数の型は E ではなく Object なので、プログラマは自由にどんなオブジェクトでも削除しようとすることができる。このような振舞いは、予期せぬオブジェクトの保持やメモリリークにつながる可能性がある[Techtalk 2007]。

適合コード

コレクションから削除されるオブジェクトの型はコレクションの要素の型と一致しなければならない。また、数値格上げとボクシングは予期せぬオブジェクト型を生成する可能性がある。以下の適合コードでは、明示的にshortにキャストすることで、ボクシングの結果の型が想定どおりになるようにしている。

public class ShortSet {
  public static void main(String[] args) {
    HashSet<Short> s = new HashSet<Short>();
      for (short i = 0; i < 100; i++) {
        s.add(i);
        s.remove((short)(i - 1));  // Short を削除
      }
    System.out.println(s.size());
  }
}
リスク評価

ボクシングで予期せぬ型のオブジェクトが生成されると、Collections ライブラリなどの API が何のエラーも出さずに失敗する可能性がある。その結果、意図せぬオブジェクトの保持、メモリリーク、プログラムの誤った処理につながる可能性がある。

ルール 深刻度 可能性 修正コスト 優先度 レベル
EXP04-J P6 L2
自動検出

Collection.remove() の呼出しにおいて、実引数の型がコレクションの要素の型と一致しないことを検出するのは容易である。ごくまれにはそのような呼出しを意図して行うことがあるかもしれないが、ほとんどの場合はコーディングエラーによるものであろう。他の API についても自動検出は可能でる。

参考文献
[Core Java 2004] Chapter 5
[JLS 2005] §5.1.7, "Boxing Conversions"
[Techtalk 2007] "The Joy of Sets"
翻訳元

これは以下のページを翻訳したものです。

EXP04-J. Ensure that autoboxed values have the intended type (revision 125)

Top へ

Topへ
最新情報(RSSメーリングリストTwitter