java - 将对象的防御性副本添加到哈希集中

标签 java hashset defensive-programming defensive-copy

目前我有这个代码:

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

如果需要,学生代码:

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

谢谢

最佳答案

你做得对,但有一些错误,因为你是写在纸上的。如果您将其重写到程序中,由于这一行,它将无法编译

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

需要替换为

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

请注意,您正在添加新的学生,但字段是由现有引用初始化的,这会导致浅复制 - 对象不同,但共享内容。但是,String 类是不可变,这意味着修改字符串的每个方法都会创建应用修改的新字符串,而旧字符串保持不变。因此,即使原始学生和它的副本共享内容,字符串修改也不会互相影响,因此我们可以说它的行为类似于防御副本

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"); 

这是一个真正的防御性复制(深层复制)的示例:

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

出于效率原因,如果您知道您正在使用不可变的类,只需复制它们的引用即可。

关于java - 将对象的防御性副本添加到哈希集中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44161371/

相关文章:

java - 在java中返回多个map<string,string>

java - RuntimeExceptions 的进位抛出声明

c# - 获取对其构造函数抛出异常的实例的引用

java - 如何使用Maven Shade插件?

带有 alpha 的 JavaFX 8 Canvas 快照

值受键的类型参数限制的 Java 映射

java - 使用实现接口(interface)的枚举的 EnumSet

c# - 是否有一种类型同时包含 : List<T> and also HashSet<T>?

java - HashSet 项等于,但 HashSet 不包含

c++ - 0xDEADBEEF 相当于 64 位开发?