Java,使类不可变 [英] Java, Making a class Immutable

查看:58
本文介绍了Java,使类不可变的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在网上遇到了这个练习,在那里我有两个课,我应该使 Tutor 类不可变.但是,我唯一想到的就是在 name 字段中添加 final .对于构造函数,我认为不需要更改 name 变量的初始化,因为 String 是不可变的.我不确定如何处理集合以及如何使构造函数的这一部分不可变.根据练习,我不应该更改Student类(我看到它是可变的)

I came across this exercise online where I have two classes and I'm supposed to make the Tutor class immutable. However, the only thing I can think of is adding final to name field. When it comes to the constructor, I don't think I need to change the initialisation of the name variable as String is immutable. I'm not sure how to approach the collection and how to make this part of the constructor immutable. According to the exercise, I'm not supposed to change the Student class (which I can see is mutable)

public class Student {    
    private String name;
    private String course;

    public Student(String name, String course) {    
        this.name = name;
        this.course = course;    
    }

    public String getName() {
        return name;
    }

    public String getCourse() {
        return course;
    }

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

    public void setCourse(String course) {
        this.course = course;
    }
}

public final class Tutor {
    private String name;
    private final Set<Student> tutees;

    public Tutor(String name, Student[] students) {
        this.name = name;
        tutees = new HashSet<Student>();
        for (int i = 0; i < students.length; i++)
            tutees.add(students[i]);
    }

    public Set<Student> getTutees() {
        return Collections.unmodifiableSet(tutees);
    }

    public String getName() {
        return name;
    }
}

推荐答案

Tutor 类提供了许多促进其不变性的方面:

The Tutor class presents many aspects promoting its immutability :

  • 这堂课是最后的
  • Set< Student> 受保护免受修改
  • 没有允许直接更改类状态的方法

但是,构造函数的防御性副本不完整.
它还必须复制所传递数组的 Student s元素.否则,构造函数的客户端可以更改它们的任何实例,并使 Tutor 实例可变,例如:

However, the defensive copy of the constructor is not complete.
It also has to copy the Students elements of the array passed. Otherwise the client of the constructor may change any instance of them and make so the Tutor instance mutable such as :

Student[] students = ...;
Tutor tutor = new Tutor(name, students);
students[0].setName("new Name!"); // break the immutability of Tutor

您应该写类似:

public Tutor(String name, Student[] students){
  this.name = name;
  tutees = new HashSet<Student>();
  for (Student student : students){   
      Student copy = new Student(student.getName(), 
                                    student.getCourse());
      tutees.add(copy);
   }     
}

另外请注意, getTutees()返回的 Set 是不可修改的,但其中包含的元素是 Student 可变的.因此,要使教师不可变,您还必须在返回 getTutees()如:

Additionally note that the Set returned by getTutees() is unmodifiable but elements contained in are as Student is mutable. So to make Tutor immutable you also have to create a copy of the Student elements as you return getTutees() such as :

public Set<Student> getTutees(){
   Set<Student> students = new HashSet<>();
   for (Student student : tutees){
      Student copy = new Student(student.getName(), 
                                    student.getCourse());
      students.add(copy);
   }     
   return Collections.unmodifiableSet(students);
}

您可能会注意到,要在这些条件下保持不变(我们希望是不变的,但包含引用可变实例的集合的实例),则需要编写更多代码(以读取/维护/测试)并执行更多处理(执行起来很慢).
如果 Student 是一个不可变的类,则原始的 getTutees()和原始的构造函数就足够了.

As you may notice, getting the immutability in these conditions (an instance that we wish immutable but that contains a collection referencing mutable instances) requires to write more code (to read/to maintain/to test) and to perform more processing (so slower to execute).
If Student was an immutable class, the original getTutees() and the original constructor would be enough.

这篇关于Java,使类不可变的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆