web-dev-qa-db-ja.com

日付またはリストを使用して、単純なゲッターおよびセッターメソッドでソナーの問題を解決します

私はこのゲッター/セッターをEclipseソースメニューからリストするように書きます:

public Date getDate() {
    return date;
}

public void setDate(Date date) {
    this.date = date;
}

そしてソナーは2つの問題を報告しています:

「日付」のコピーを返し、「日付」のコピーを保存します

説明付き

「ミュータブルメンバーは直接保存または返却しないでください」

およびサンプルコード:

public String [] getStrings() {
    return strings.clone();}

public void setStrings(String [] strings) {
    this.strings = strings.clone();}

日付がnullの場合、NullPointerExceptionがスローされると思います。次に、コードを次のように変更しました。

public Date getDate() {
    if (this.date != null) {
        return new Date(this.date.getTime());
    } else {
        return null;
    }
}

public void setDate(Date date) {
    if (date != null) {
        this.date = new Date(date.getTime());
    } else {
        this.date = null;
    }
}

そして今、他の問題をマークします:

「オブジェクトをnullに割り当てるのは、コードの臭いです。リファクタリングを検討してください」。

インターネットで検索し、新しい配列を設定または返すことは私にとって解決策ではありません。既存の以前のリストを上書きするために、セッターパラメーターがnullの場合、リストをnullのままにしておきたいです。

Listについても同じ問題があり、空のListに対して新しいArrayListの代わりにnullを返す/保持したいと思います。そしてこの場合、セッターはもう1つの問題をマークします。

「nullの代わりに空のコレクションを返します。」.

この問題の解決策は何ですか?

8
Corporativo

Java 8で、空の日付を処理したくない場合は、Optionalを使用すると役立つ場合があります。

編集:「POJO」クラスの例

public class Toto {

    public Optional<Date> myDate;

    public Optional<Date> getMyDate() {
        return this.myDate;
    }

    public void setMyDate(final Date myDate) {
        this.myDate = Optional.ofNullable(myDate);
    }

}

コードの使用例:

Toto toto = new Toto();
toto.setMyDate(null);
System.out.println("Value is null ? " + toto.getMyDate().isPresent());
System.out.println("Value: " + toto.getMyDate().orElse(new Date()));

Toto.setMyDate(...)を具体的な日付値で変更して、何が起こるかを確認してください。

オプションとは何か、またはその使用方法がわからない場合は、多くの例を見つけることができます。

[〜#〜] but [〜#〜]:これは違反の問題を解決する方法にすぎず、Bradの発言に完全に同意します。オプションはタイプとして使用することを意図していませんが、詳細潜在的な空/ヌルリターンの契約のように。一般に、違反が正しくない場合は、違反を修正するためだけにコードを悪い方法で修正しないでください。そしてあなたの場合、私はあなたが違反を無視するべきだと思います(残念ながらソナーのもののほとんどとして)

本当にJava 8およびOptionalをコードで使用したい場合、POJOクラスは次のようになります(ゲッターでのコントラクトとしてのOptionalの使用のみ)

public class Toto {


    public Date myDate;

    public Optional<Date> getMyDate() {
        return Optional.ofNullable(this.myDate);
    }

    public void setMyDate(final Date myDate) {
        this.myDate = myDate;
    }

}

こちらです、

  • Beanはシリアル化可能のままです(オプションではありません)
  • あなたはまだあなたの「クライアント」コードがあなたのプロパティの空/ null値にどのように振る舞うかを選択できるようにします
  • コードを変更するのではなく、Sonar違反を誤検知として構成します。
3
kij

一般に、静的分析ツールを使用してコードが価値があることを確認する一方で、ポップアップするすべての警告を盲目的に修正するべきではありません。トリガーされた問題を分析し、それが実際にコンテキストに当てはまるかどうかを確認する必要があります。

今あなたが言及している問題に対処するために

「日付」のコピーを返し、「日付」のコピーを保存します

これは有効なもののようです。防御的であり、ゲッター/セッターを介して可変状態を公開しないことをお勧めします。したがって、getter/setterで防御コピーを作成する必要があります。これは、あなたが行った方法で、または不変のオブジェクトを提供するnew Java TimeAPIを使用して行うことができます。

オブジェクトをnullに割り当てるのは、コードの臭いです。リファクタリングを検討する

IMO疑わしいもの。この問題は、PMDプラグイン(コードを分析するツールであり、SonarQubeがレポートを表示している)によって発生します。このルールによって問題が発生します http://pmd.sourceforge.net/pmd-4.3.0/rules/controversial.html#NullAssignment 、物議を醸すカテゴリにあることがわかります。コードに問題はないと思います。適切なアクションは、この警告を無視して、問題を「修正されない」とマークすることです。品質プロファイル設定でこの特定のルールを使用しないようにSonarQubeを構成することもできます。

Nullではなく空のコレクションを返します。

あなたはそれを引き起こしているコードを提供しませんでしたが、これは有効なアドバイスのようです。一般に、nullよりも空のコレクションを返す方が適切です。

1
Tibor Blenessy

セッターで明示的にnullを設定する必要はなく、渡される値を次のように使用するだけです...

public void setDate(Date date) {
    if (date != null) {
        this.date = new Date(date.getTime());
    } else {
        this.date = date;
    }
}

個人的には、可能な限りnull値をValueオブジェクトに許可することは決してありませんが、それは私の考えているコーディングスタイルにすぎません。

コンストラクターですべての値を設定し、nullを許可しない不変の値オブジェクトを優先することをお勧めします。このスタイルは、Javaを期待するすべてのサードパーティライブラリに適しているとは限りません。 = Bean getter/setterなので、コードを単純化するために効果的に使用できる場所に注意してください。

編集

上記のコードでも警告が表示され、「プロパティがまだ設定されていません」機能が必要な場合は、次のような「nullオブジェクト」を定義することもできます。

public static final Date NO_DATE = new Date(Long.MIN_VALUE);

public void setDate(Date date) {
    this.date = (date == null) ? NO_DATE : new Date(date.getTime());
}

このクラスのユーザーは、このようなNO_DATEオブジェクトを参照できますが、これでも読み取り可能なコードになります。

if(toto.getDate() != NO_DATE) ...

または、これを別のメソッドにカプセル化して、このように使用します

if(toto.hasDate()) ...

もちろん、これはJava 8 @kijからのオプションのアプローチよりも多くの利点を追加しませんが、Javaのどのバージョンでも機能します

1
Brad

ゲッターとセッターを手動で作成するのではなく、ロンボクライブラリを使用することをお勧めします。それは自動的にそのようなソナーの問題を回避します。

0
k_b