Java 若类并没有实现cloneable,那个么我们如何获得不可变对象呢
我对在HashMap中填充值没有什么疑问 我想要一个HashMap接受“Student”作为键,“Details”作为值。 既然hashMap的键应该是不可变的,我有一些疑问,如果Java 若类并没有实现cloneable,那个么我们如何获得不可变对象呢,java,immutability,cloneable,Java,Immutability,Cloneable,我对在HashMap中填充值没有什么疑问 我想要一个HashMap接受“Student”作为键,“Details”作为值。 既然hashMap的键应该是不可变的,我有一些疑问,如果 学生班级不可克隆 学生班有参考,而参考又有“实验室” 公共班级学生{ 私有字符串id; 私有字符串名称; 私人部门; 公立学生(字符串id、字符串名称、系) { 这个.id=id; this.name=name; this.dept=dept; } 公共部门 { 退回本部门; } } 公共课部{ 私人
公共班级学生{
私有字符串id;
私有字符串名称;
私人部门;
公立学生(字符串id、字符串名称、系)
{
这个.id=id;
this.name=name;
this.dept=dept;
}
公共部门
{
退回本部门;
}
}
公共课部{
私人字符串部门;
私人实验室;
公共部门(字符串部门、实验室)
{
this.deptId=deptId;
this.lab=lab;
}
公共空间实验室(实验室)
{
this.lab=lab;
}
}
公共班级实验室{
私有字符串labId;
私有字符串labName;
公共实验室(字符串labId、字符串labName)
{
this.labId=labId;
this.labName=labName;
}
}
公开课学生详情
{
私有字符串父名称;
专用字符串地址
公共学生详细信息(字符串父名称、字符串地址)
{
this.fatherName=fatherName;
这个地址=地址;
}
}
公共班级学生维护者{
公共静态void main(字符串[]args)
{
StudentDetails stDetails=新的StudentDetails(“约翰”、“孟买”);
实验室=新实验室(“100”,“CS”);
部门=新部门(“900”,实验室);
学生st=新生(“3000”,系);
Map studentMaintainer=new ArrayList();
studentmainter.put(st,st详细信息);
}
}
现在,如果Department和Lab来自第三方JAR,那么如果Student hashCode是(primeNumber+Student.id+Department.id+Lab.id).hashCode()[只是一些奇怪的情况],我如何在地图中使用Student对象 据我所知,不变性与可克隆性无关,事实恰恰相反。不变性与声明类final和使用不可变字段、不可重写方法、无setter方法、返回字段或不可变字段深度副本的getter方法等有更多关系。。。请阅读更多关于这方面的内容 您的代码还有一个伪构造函数:
public void Student(String id, String name, Department dept)
{
this.id=id;
this.name=name;
this.dept=dept;
}
真正的构造函数不应声明为返回任何内容,甚至不应声明为void。最好是:
// note the difference?
public Student(String id, String name, Department dept)
{
this.id=id;
this.name=name;
this.dept=dept;
}
此外,如果学生类要作为HashMap的键很好地工作,就应该正确地重写equals和hashCode。就我所知,不变性与Cloneable无关,事实上恰恰相反。不变性与声明类final和使用不可变字段、不可重写方法、无setter方法、返回字段或不可变字段深度副本的getter方法等有更多关系。。。请阅读更多关于这方面的内容 您的代码还有一个伪构造函数:
public void Student(String id, String name, Department dept)
{
this.id=id;
this.name=name;
this.dept=dept;
}
真正的构造函数不应声明为返回任何内容,甚至不应声明为void。最好是:
// note the difference?
public Student(String id, String name, Department dept)
{
this.id=id;
this.name=name;
this.dept=dept;
}
此外,如果学生类要作为HashMap的键很好地工作,就应该正确地重写equals和hashCode
现在,即使学生是可克隆的,我也可以得到系里的参考资料
并调用setLab()以更改StudentObject。(我错了吗?)
你说得对。这可能发生,并可能导致您的学生类出现变异。对于不可变的Student
实例,您必须不能修改其任何字段[0]。这包括在其中一个字段上调用setter方法
现在,如果部门和实验室来自第三方JAR,我如何使用
如果Student hashCode为
(primeNumber+Student.id+Department.id+Lab.id).hashcode()[只是一些
怪案]
这是一个很好的问题。很明显,您不能仅仅将类更改为不可变的,因为您无法控制它们,所以您可能需要有点创造性。可能的解决办法:
- 如果要使用的第三方对象是接口,则可以使用自己的类型实现该接口,其中每个mutator方法的主体都会抛出一个异常(例如,
)。这样做的好处是,您仍然可以在代码库中引用第三方类,但缺点是调用mutator方法将在运行时失败,而不是在编译时失败java.util.Collections.unmdfiableList
- 在您自己的代码库中编写适配器,如下所示:
这有一个优点,您知道在编译时,类是不能变异的public final class MyImmutableDepartment { private final MyImmutableLab lab; private final String departmentId; public MyImmutableDepartment(Department thirdPartyMutableDepartment) { this.departmentId = thirdPartyMutableDepartment.getId(); this.lab = new MyImmutableLab(thirdPartyMutableDepartment.getLab()); } // getters and the MyImmutableLab class left as an exercise }
Student
实例,您必须不能修改其任何字段[0]。这包括在其中一个字段上调用setter方法
现在,如果部门和实验室来自第三方JAR,我如何使用
如果Student hashCode为
(primeNumber+Student.id+Department.id+Lab.id).hashcode()[只是一些
怪案]
这是一个很好的问题。很明显,您不能仅仅将类更改为不可变的,因为您无法控制它们,所以您可能需要有点创造性。可能的解决方案