Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 若类并没有实现cloneable,那个么我们如何获得不可变对象呢_Java_Immutability_Cloneable - Fatal编程技术网

Java 若类并没有实现cloneable,那个么我们如何获得不可变对象呢

Java 若类并没有实现cloneable,那个么我们如何获得不可变对象呢,java,immutability,cloneable,Java,Immutability,Cloneable,我对在HashMap中填充值没有什么疑问 我想要一个HashMap接受“Student”作为键,“Details”作为值。 既然hashMap的键应该是不可变的,我有一些疑问,如果 学生班级不可克隆 学生班有参考,而参考又有“实验室” 公共班级学生{ 私有字符串id; 私有字符串名称; 私人部门; 公立学生(字符串id、字符串名称、系) { 这个.id=id; this.name=name; this.dept=dept; } 公共部门 { 退回本部门; } } 公共课部{ 私人

我对在HashMap中填充值没有什么疑问

我想要一个HashMap接受“Student”作为键,“Details”作为值。 既然hashMap的键应该是不可变的,我有一些疑问,如果

  • 学生班级不可克隆
  • 学生班有参考,而参考又有“实验室”

    公共班级学生{
    私有字符串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详细信息);
    }
    }
    
  • 现在,即使学生是可克隆的,我也可以获取部门的引用并调用setLab(),这将更改StudentObject。(我错了吗?)


    现在,如果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方法的主体都会抛出一个异常(例如,
      java.util.Collections.unmdfiableList
      )。这样做的好处是,您仍然可以在代码库中引用第三方类,但缺点是调用mutator方法将在运行时失败,而不是在编译时失败
    • 在您自己的代码库中编写适配器,如下所示:

      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
      }
      
      这有一个优点,您知道在编译时,类是不能变异的

    这两种方法的缺点是,基本上必须从第三方库镜像每个类,以确保它们是不可变的

    我认为没有其他选择

    [0]在某些情况下,这是可能的,并且可以用于内部缓存,但在学习时,这是一个不错的指导原则

    现在,即使学生是可克隆的,我也可以得到系里的参考资料 并调用setLab()以更改StudentObject。(我错了吗?)

    你说得对。这可能发生,并可能导致您的学生类出现变异。对于不可变的
    Student
    实例,您必须不能修改其任何字段[0]。这包括在其中一个字段上调用setter方法

    现在,如果部门和实验室来自第三方JAR,我如何使用 如果Student hashCode为 (primeNumber+Student.id+Department.id+Lab.id).hashcode()[只是一些 怪案]

    这是一个很好的问题。很明显,您不能仅仅将类更改为不可变的,因为您无法控制它们,所以您可能需要有点创造性。可能的解决方案