2

タイトルがすべてを物語っています。

たとえば、従業員クラスがあります

class Employee
{
   private Date joinDate;

   public Date getJoinDate()
   {
       return joinDate;    
   }
}

ここで getJoinDate は、内部の joinDate オブジェクトへの参照を返します。FindBug でコードを分析すると、「... ClassXYZ.pqrDate を返すことで内部表現が公開される可能性があります」という「悪意のあるコードの脆弱性」という警告が表示されました。

そのため、このゲッターにアクセスするコードは、インスタンス外のクラスのこのインスタンスに格納されている日付を変更できる可能性があります。だから私はコピーコンストラクタを使うべきですか

Q1. コピーコンストラクタを書くべきかどうか(または他のアプローチに従うべきか)

class Employee
{
   private Date joinDate;

   Employee(Employee e)      //copy constructor
   {
       joinDate = e.joinDate;
   }

   public Date getJoinDate()
   {
       return joinDate;    
   }
}

Q2 フレームワーク オブジェクトのコピー コンストラクターを作成するにはどうすればよいですか? ビジネス オブジェクトのコピー コンストラクターは定義できますが、フレームワーク オブジェクトのコピー コンストラクターは定義できません。インスタンスを受け入れるフレームワーククラスの新しいインスタンスを返すすべてのメソッドを持つ汎用ユーティリティクラスが必要ですか?

class CopyConstructorUtil
{
    public Date copyDate(Date date)
    {
         return new Date(date.getTime());
    }
    //....
}

また、Java Object クラスは、すべてのクラスに継承される clone() メソッドを提供します。しかし、それはオブジェクトを返します。では、単純に getters 内でキャストする必要がありますか? :

class Employee
{
   private Date joinDate;

   public Date getJoinDate()
   {
       return (Date)joinDate.clone();    
   }
}

Q3. どのアプローチが望ましいですか?または、他のアプローチを使用する必要がありますか?

4

4 に答える 4

2

問題は、Javaのデータ型の可変性です。したがって、コピーコンストラクターを使用しても、新しいDateをインスタンス化せずに、オブジェクトの状態をリークすることになります。

あなたは(ゲッターとセッターの両方を変更する必要があります)として行う必要があります。そうでない場合は、オブジェクトの状態をリークしています。

public Date getJoinDate() {
    return new Date(joinDate.getTime());
}

public void setDate(Date joinDate) {
    this.joinDate = new Date(joinDate.getTime());
}

効果的なJava、第2版で述べたように、次のようなセキュリティの問題になる可能性があるため、呼び出しclone()はあまり良くありません。

class MyDate extends Date {
    public Object clone() {
        return this;
    }
}

これで、このオブジェクトを日付として渡すことができます。また、呼び出し元はオブジェクトへの参照を保持できるため、クローン作成後でもオブジェクトの状態を操作できます。

于 2013-02-06T07:30:13.640 に答える
2

Date Objectas として宣言しfinal、コピー コンストラクターを使用することをお勧めします。

「Clone() が Java で多くの欠点を持っている理由について」リンクというすばらしい記事があります。

class Employee{
    private final Date joinDate;
    public Employee(Date joinDate,...){
         this.joinDate = joinDate;
    }
    public Date getJoinDate(){
         return new Date(joinDate);    
    }
}
于 2013-02-06T07:17:04.577 に答える
1

Employees クラスのコピーコンストラクターは、あなたが返す日付を変更することを誰にも妨げません

Date.setTime(long)

それらを返す前に、内部オブジェクトを複製します。または、複製するのではなく、複製コードの前に使用する方法を使用します。このような:

class Employee {
   private final Date joinDate;

   public Date getJoinDate() {
       return new Date(joinDate.getTime());
   }
}

このソリューションはキャストを必要とせず、だれもが内部メンバーを編集できないようにします。

于 2013-02-06T07:20:28.457 に答える
0

私たちのプロジェクトでは、この findbugs ルールを無効にしています。Findbigs は true です。日付は変更可能なオブジェクトであるため、本当に変更を防止したい場合は、次の方法以外に選択肢はありません。

  • インスタンスの公開を防ぐために、日付を long として返します

  • ゲッターが設定されるたびにコピーを行う

ただし、毎回コピーを行うコードも考慮する必要があります。このため、このルールを無効にしてこの脆弱性を受け入れています。

于 2013-02-06T07:23:32.813 に答える