Search code examples
javahashsetdefensive-programmingdefensive-copy

add a defensive copy of an object to a hashset


Currently I have this code:

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]);
}

I'm trying to rewrite it (just on paper) so that it makes/adds defensive copies of students rather than directly adding them into the hashset and am wondering if the following code would do so:

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](students.getName(), students.getCourse());
}

Code for Student if needed:

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;
 }
}   

thanks


Solution

  • You are doing it right, but with some mistakes, since you are writing it on paper. If you rewrite it into the program, it would not compile, due of this line

    tutees.add(students[i](students.getName(), students.getCourse());
    

    which need to be replaced by

    tutees.add(new Student(students[i].getName(), students[i].getCourse());
    

    Note, you are adding new Student, but fields are initilaized by existing references, which results in shallow-copy - objects are different but are sharing the content. However, String class is immutable which means that each method which modifies string creates new string with applied modifications and the old one remains the same. So even if original student and it's copy shares the content, string modifications can not affect each other, therefore we can say it is something that acts like defensive-copy.

    Student original = new Student("name", "course");
    Student copy = new Student(original.getName(), original.getCourse());
    // does not change the name of the copy
    String modifiedName = copy.getName().replaceAll("a", "b"); 
    

    Here is an example of true defensive-copy (deep-copy):

    Student deepCopy = new Student(
            new String(original.getName()), 
            new String(original.getCourse())
    );
    

    For efficiency reasons, if you know you are working with classes that are immutable, just copy their references.