2017-05-24 81 views
0

目前我有这样的代码:对象的防守副本添加到HashSet

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

我试图这样,它使/添加,而不是学生的防守副本重写它(只是纸上谈兵)直接将它们添加到HashSet的,我想知道,如果下面的代码将这样做:如果需要的学生

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

谢谢

+0

首先使用编译器。它会发现至少一个错误。接下来,请考虑为学生编写一个构造函数,将Student作为参数 - 封装在Student类中复制学生需要的内容。 –

回答

2

你做得对,但有一些错误,因为你写在纸上。如果你把它改写成程序,它不会编译由于这一行的,

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

需要由

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

注意更换,您要添加新的Student,但场由initilaized 现有参考文献,这导致浅拷贝-对象不同但共享内容。然而,String类是immutable这意味着修改字符串的每个方法都会创建具有应用修改的新字符串,并且旧字段保持不变。因此,即使原始学生和它的副本共享内容,字符串修改也不会互相影响,因此我们可以说这是一种类似防御副本的行为。

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

为了提高效率,如果你知道你与那些immutable类的工作,只是复制他们的参考。

+0

感谢matoni,我认为这足以解决问题!怀疑我需要一个“新”在那里的地方,但它周围:) – pxdr0

1

您已经确定了将可变学生放入Set这个问题是一个坏主意。因为它违反了集合的合约,所以你不想在集合中改变它。

创建一个副本可以处理症状,但不会处理潜在的问题。问题是你的学生班是可变的。如果你让你的Student类不可变,你不需要担心复制,并且它会显着减少错误。

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

如果学生更改名称 - 发生这种情况的频率如何?在你的系统中,你可能根本不需要对它进行建模 - 或者改变课程,你只需创建一个新学生并删除旧的,不正确的。

+0

感谢迈克尔不能让我的头!我知道学生是可变的是一个潜在的问题,只是这个特殊的练习要求学生不要被改变。当然,在真实生活场景中解决这个问题要容易得多 – pxdr0