「EI_EXPOSE_REP2」とfindbugsに怒られたら


きっかけ

findbugsをつかっていて、EI_EXPOSE_REP2 というのが、あって気になって調べてみました。

詳細

May expose internal representation by incorporating reference to mutable object

平たくいうと、内部で保持するためのデータを、外部からのmutableなものをそのまま使っているので、外から変更できてしまう、ということです。

よくある具体例は、配列やリストです。

Example1.java

public  class Example1 {

  private int[] numbers;

  public Example1(int[] numbers) {
    this.numbers = numbers;
  }

  public int[] getNumbers() {
    return this.numbers;
  } 

}

int[] numbers = {1,2,3};
Example1 ex1 = new Example(numbers);

// コンストラクタにわたしものの中身を変更
numbers[0] = 10;

ex1.getNumbers();
// => {10,2,3}

上記のように、privateにして内部に隠蔽したつもりなのに、もとがmutableだとこのように外から中身を変えられてしまいます。Listでも同様のことができ、#clear()をつかってしまうと外から中身を空にすることも... Java7までならDateもこれにあたります。

解決策

Object指向的に好ましくないということで、findbugsで警告がでてきます。回避策もでていて、

  • cloneしたものをわたす
  • immutableなものにかえる

の2つです。ごもっともですねw

Javaでimmutableとなると、Guavaなどのライブラリをつかうのが手っ取り早いかと。

所感

コンストラクタやsetterの引数がmutableかどうかは気をつけないとですね。
こういう風に、バグの原因になりそうなものや、悪いパターンを気づきやすくなるのでfindbugsはありがたいです。経験が浅いメンバーがいるプロジェクトほど、こういったものがあるとよいのですが。

参考サイト