我有以下课程:
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 类成为纯粹的不可变类?
答案 0 :(得分:3)
对于非原始字段,在 getters 中,使用此结构
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);
}
}
因此,只需创建与之前的
相等的新部门实例 P.S。在我的例子中,你可以看到纯不可变的类
修改强>
您还可以添加到Department类copy-contructor
public Department(final Department dep)
{ ... }
和雇主
getDepartment()
{
return new Department(department);
}
答案 1 :(得分:1)
如果你不喜欢删除setter并在构造函数中进行初始化,你可以考虑在getter中返回不可变(从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()
中实现方法Department
(将实现接口Cloneable
)。
如果您需要能够修改Department
,这种方法是合适的,但Emp
类的对象应该不受那些外部修改的影响。
答案 2 :(得分:0)
制作所有属性final
,并删除所有设置者
答案 3 :(得分:0)
在Department中实施 clone(),并使 Emp 在 getDepartment()中返回部门的克隆。
如果构造Emp中使用的部门的引用在构造之后可用,那么Emp的构造函数应该克隆给定的部门。
答案 4 :(得分:0)
参见Efffective Java:
第15项:尽量减少可变性 - 遵循5条规则。