0

私は次のクラスを持っています:

Emp.java

final public class Emp {

    private Integer id;
    private String name;
    private Department department;

    public Emp(Integer id, String name, Department department) {
        this.id = id;
        this.name = name;
        this.department = department;
    }

    public Department getDepartment() {
        return department;
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

Department.java

public class Department {

    private Integer id;
    private String name;

    public Department(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }
}

EmployeeTest.java

public class EmployeeTest {

    public static void main(String args[]) {
        Department dept1 = new Department(1, "dept1");
        Emp emp = new Emp(1, "emp1", dept1);
        emp.getDepartment().setName("dept2");
        System.out.println("emp = "+emp);

    }
}

ここで、 Empクラスは純粋に不変のクラスではありません。これは、どういうわけか、Departmentの値を変更できるためです(例を参照)。

Empクラスを純粋な不変クラスにするための最良の変更は何ですか?

4

5 に答える 5

3

非プリミティブフィールドの ゲッターでは、この構造を使用します

public class Line {

   private final Point start;
   private final Point end;

   public Line(final Point start, final Point end) {
       this.start = new Point(start);
       this.end = new Point(end);
   }

   public Point getStart() {
       return new Point(start);
   }

   public Point getEnd() {
       return new Point(end);
   }
}  

したがって、以前と同じ部門の新しいインスタンスを作成するだけです。

PS私の例では、純粋な不変クラスを見ることができます
編集:
Departmentクラスに追加することもできますcopy-contructor

public Department(final Department dep)  
{ ... } 

そして雇用主に

getDepartment()  
{  
   return new Department(department);  
}
于 2012-08-20T09:15:38.950 に答える
1

Empセッターを削除してコンストラクターで初期化を行うのが好きでない場合は、オブジェクトのコピーをWebオブジェクトにする不変の(クラスの観点から)オブジェクトをゲッターで返すことを検討できます( https://stackoverflowを参照)。 com / a / 128712/1579085)。

final public class Emp {

    private Integer id;
    private String name;
    private Department department;

    public Emp(Integer id, String name, Department department) {
        this.id = id;
        this.name = name;
        this.department = (Department) department.clone();
    }

    public Department getDepartment() {
        return (Department) department.clone();
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

もちろん、(インターフェイスを実装する)のメソッドclone()を実装します。DepartmentCloneable

このアプローチは、を変更できる必要がある場合に適してDepartmentいますが、クラスのオブジェクトはEmpそれらの外部変更から安全である必要があります。

于 2012-08-20T09:31:45.353 に答える
1

効果的なJavaを参照してください。

項目15:可変性を最小限に抑える–従うべき5つのルール。

  1. オブジェクトの状態を変更するメソッドを提供しないでください
  2. クラスを拡張できないことを確認します
  3. すべてのフィールドを最終的にする
  4. すべてのフィールドを非公開にする
  5. 可変コンポーネントへの排他的アクセスを確保する
于 2012-08-20T09:33:41.597 に答える
0

すべての属性finalを作成し、すべてのセッターを削除します

于 2012-08-20T09:08:26.730 に答える
0

Departmentにclone()を実装し、 EmpgetDepartment()にdepartmentのクローンを返すようにします。

Empの構築に使用されたDepartmentへの参照が構築後に利用可能である場合、Empのコンストラクターは指定されたDepartmentのクローンを作成する必要があります。

于 2012-08-20T09:09:52.023 に答える