Java 使纯不可变类
我有以下课程: Emp.javaJava 使纯不可变类,java,Java,我有以下课程: 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; t
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;
}
}
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;
}
}
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);
}
}
Department.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;
}
}
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;
}
}
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);
}
}
EmployeeTest.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;
}
}
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;
}
}
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成为纯不可变类的最佳更改是什么?使所有属性成为最终属性,并删除所有设置器使所有属性成为最终属性,并删除所有设置器实现克隆()在部门中创建Emp并在getDepartment()中返回部门的克隆 如果在构建Emp时使用的部门引用在构建后可用,则Emp的构造函数应克隆给定的部门。在部门中实现克隆(),并在getDepartment()中使Emp返回部门的克隆
如果在构造Emp时使用的部门引用在构造后可用,则Emp的构造函数应克隆给定的部门。在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);
}
}
所以,只需创建一个新的department实例,该实例等于上一个department实例
另外,在我的示例中,您可以看到纯不可变类编辑:
也可以添加到Department类副本构造函数
public Department(final Department dep)
{ ... }
和雇主
getDepartment()
{
return new Department(department);
}
在非原语字段的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);
}
}
所以,只需创建一个新的department实例,该实例等于上一个department实例
另外,在我的示例中,您可以看到纯不可变类编辑:
也可以添加到Department类副本构造函数
public Department(final Department dep)
{ ... }
和雇主
getDepartment()
{
return new Department(department);
}
如果您不喜欢删除setter并在构造函数中进行初始化,那么可以考虑返回不可变(从
Emp
class的角度)对象,它将在getter中创建web对象的副本(请参阅)
当然,在部门
中实现方法clone()
(这将实现接口Cloneable
)
如果您需要能够修改
Department
,但是Emp
类的对象应该不会受到这些外部修改的影响,那么这种方法是合适的。如果您不喜欢删除setter并在构造函数中进行初始化,您可以考虑返回immutable(从Emp
class)对象的角度来看,它将在getter中创建web对象的副本(请参阅)
当然,在部门
中实现方法clone()
(这将实现接口Cloneable
)
如果您需要能够修改Department
,但Emp
类的对象应该不会受到这些外部修改的影响,那么这种方法是合适的。请参阅effective Java:
第15项:最小化易变性–要遵循的5条规则
为什么你需要部门中的设置者?部门类可能也可以在其他地方使用…我的意图是使Emp类完全不可变,而不是部门。你需要的技术称为防御性复制。谷歌随时可供你使用。为什么你需要部门中的设置者?我可能会有这样的机会nt类也可以在其他地方使用…我的意图是使Emp类完全不可变,而不是部门。你需要的技术叫做防御复制。谷歌由你支配。@Ilya我没有注意到。这使我的答案不可用。@Ilya我没有注意到。这使我的答案不可用。这将使他的所有类不可变这不是他的本意。
部门
应该是可变的。这将使他的所有类都不可变,这不是他的本意。部门
应该是可变的。部门
仍然可以在代码中更改。您还必须在构造函数中进行复制/克隆。@maba是的,但现在是Emp
>类是安全的,没有人可以通过改变department
(我会更正我的答案)来破坏它的逻辑。但是如果我有一个dep
到department
的引用,并在构造函数中使用它,那么我可以通过执行dep.setName(“其他”)来更新department
并更改了部门
@maba,在这种情况下,可以在构造函数中再次使用副本。对不起,忘记在代码中输入。在代码中仍然可以更改部门
。@maba是的,但是现在Emp
类是安全的,没有人可以破坏它它的逻辑是通过改变部门
(我会更正我的答案。)但是如果我有一个dep
到部门
的引用,并在构造函数中使用它,那么我可以通过执行dep.setName(“其他”)来更新部门
并更改了部门
@maba,在这种情况下,可以再次使用副本-在构造函数中。对不起,忘记输入代码。