2017-05-24 80 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