The Tutor
class presents many aspects promoting its immutability :
- the class is final
- the
Set<Student>
is protected against the modifications
- no method allowing to change directly the state of the class
However, the defensive copy of the constructor is not complete.
It also has to copy the Student
s 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
You should write something like :
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);
}
}
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);
}
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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…