スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。


--------------------------------------------------------------------------------------

メモ・・・javaでBeanを作成する際、何も考えずsetterを作るとFindBugsで警告される話

業務でjavaによる開発はeclipseを使ってます。

っで、beanクラスを作るとき以下のような手順を使っています。

package bean;

public class HogeBean {

    private String[] hogeStrAr;

}



とまでソースを打ち込んだ後、
右クリック→ソース→getterおよびsetterの生成を選びます。
すると以下のようなソースが出来上がります。

package bean;

public class HogeBean {

    private String[] hogeStrAr;

    public String[] getHogeStrAr() {
        return hogeStrAr;
    }

    public void setHogeStrAr(String[] hogeStrAr) {
        this.hogeStrAr = hogeStrAr;
    }

}



この状態で保存して一安心した状態で、FindBugsのソースチェックを行うと
getterには
----------------------------------------------------------
Bug:
bean.HogeBean.getHogeStrAr() は HogeBean.hogeStrAr を戻すことにより内部表現を暴露してしまう可能性があります。
Pattern id: EI_EXPOSE_REP, type: EI, category: MALICIOUS_CODE

オブジェクトのフィールドに格納された変更可能なオブジェクトの参照を返すと、オブジェクトの内部表現を暴露してしまいます。もしも、このオブジェクトが信頼されていないコードによってアクセスされる事が、セキュリティや、その他の重要な情報への脅威となる可能性があるため、このコードは修正すべきです。防御的コピーを行って、複製を返すのが、多くの場面で良いやり方です。
---------------------------------------------------------

setterには
---------------------------------------------------------
Bug: bean.HogeBean.setHogeStrAr(String[]) は HogeBean.hogeStrAr の中に外部の可変オブジェクトを格納することにより内部表現を暴露してしまう可能性があります。
Pattern id: EI_EXPOSE_REP2, type: EI2, category: MALICIOUS_CODE

このコードは、外部の変更可能オブジェクトを自らの実装に格納しています。もしもこのオブジェクトが信頼されていないコードによってアクセスされると、セキュリティや、その他の重要な情報への脅威となる可能性があるため、このコードは修正すべきです。防御的コピーを行って、複製を返すのが、多くの場面で良いやり方です。
---------------------------------------------------------

というメッセージが表示されてしまいます。
eclipseのgetter、setter機能をもうちょいしっかりしてほしいところです。


さて、この警告はどうやら参照渡ししたものをそのままbeanのフィールドに設定・返却しているのがよろしくないそうです。
ちょっとよろしくない理由を検証してみます。

この記事ではsetterに関して記述します。
getterはまた今度。

まずBeanにtoStringメソッドをオーバーライドを追加してBeanの内容をチェックできるように修正。


package bean;

import java.util.Arrays;

public class HogeBean {

    private String[] hogeStrAr;

    public String[] getHogeStrAr() {
        return hogeStrAr;
    }

    public void setHogeStrAr(String[] hogeStrAr) {
        this.hogeStrAr = hogeStrAr;
    }

    @Override
    public String toString() {
        return "HogeBean [hogeStrAr=" + Arrays.toString(hogeStrAr) + "]";
    }

}


そして、Beanを実際に使用するソースを作成します。

package main;

import bean.HogeBean;

public class TestHoge {

    public static void main(String[] args) {

        String[] strAr = { "りんご", "みかん", "バナナ" };

        HogeBean hogeBean = new HogeBean();
        hogeBean.setHogeStrAr(strAr);

        // 現在のBeanの状態を確認
        System.out.println(hogeBean);

        // 配列の0番目を変更してみる。
        strAr[0] = "いちご";
        // 配列操作後のBeanの状態を確認
        System.out.println(hogeBean);
    }

}


実行結果は以下のようになります。

--------------------------------------------------------------------------------------------------
HogeBean [hogeStrAr=[りんご, みかん, バナナ]]
HogeBean [hogeStrAr=[いちご, みかん, バナナ]]
--------------------------------------------------------------------------------------------------

setterを使わずにBeanの中身が変わってしまうことが問題のようです。

というわけで"setterはコピーを使って修正しろ"とのことなので、以下のように修正してみます。

    public void setHogeStrAr(String[] hogeStrAr) {
        this.hogeStrAr = (String[])hogeStrAr.clone();
    }

この状態で先ほどのTestHogeクラスを実行してみると

--------------------------------------------------------------------------------------------------
HogeBean [hogeStrAr=[りんご, みかん, バナナ]]
HogeBean [hogeStrAr=[りんご, みかん, バナナ]]
--------------------------------------------------------------------------------------------------

となりました。
めでたしめでたし・・・と思いきや、まだ罠があったりします。

意図的にBeanのhogeStrArにnullを設定しようとするとNull`PonterExceptionが発生してしまいます。

package main;

import bean.HogeBean;

public class TestHoge {

    public static void main(String[] args) {

        String[] strAr = null;

        HogeBean hogeBean = new HogeBean();
        hogeBean.setHogeStrAr(strAr);

        // 現在のBeanの状態を確認
        System.out.println(hogeBean);

    }

}



実行結果
--------------------------------------------------------------------------------------------------
Exception in thread "main" java.lang.NullPointerException
 at bean.HogeBean.setHogeStrAr(HogeBean.java:14)
 at main.TestHoge.main(TestHoge.java:13)
--------------------------------------------------------------------------------------------------


そんなわけで、この現象を回避したいためnullかどうかの分岐を入れてみます。

    public void setHogeStrAr(String[] hogeStrAr) {
        if(hogeStrAr == null){
            this.hogeStrAr = null;
        }else{
            this.hogeStrAr = (String[])hogeStrAr.clone();
        }
    }

すると実行結果は
--------------------------------------------------------------------------------------------------
HogeBean [hogeStrAr=null]
--------------------------------------------------------------------------------------------------

となりまして、解決です。
次回はgetter編
関連記事


--------------------------------------------------------------------------------------

コメントの投稿

非公開コメント

このブログについて
  • 全記事一覧(時間順)
  • このブログについて
  • 私のプロフィール
  • 当ブログで扱っている動画について
  • 記事違いなコメントのお返事

  • カテゴリー
    twitter
    カレンダー
    07 | 2017/08 | 09
    - - 1 2 3 4 5
    6 7 8 9 10 11 12
    13 14 15 16 17 18 19
    20 21 22 23 24 25 26
    27 28 29 30 31 - -
    Amazon
    でたらめな当ブログにぴったりな商品を自動で表示するみたいです。



    月別アーカイブ
    プロフィール

    たづみ

    Author:たづみ
    ・1981年生まれの男
    ・もう少し詳細なプロフィールはこちらで

    最新コメント
    アクセスランキング
    [ジャンルランキング]
    日記
    985位
    アクセスランキングを見る>>

    [サブジャンルランキング]
    会社員・OL
    203位
    アクセスランキングを見る>>


    上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。