0
package main; 
import java.util.Collections; 
import java.util.HashSet; 
import java.util.Set; 

public final class Tutor { 

    private final String name;   
    private final Set<Student> tutees;    

    public Tutor(String name, Student[] students) {   
     this.name = name;  
     this.tutees = new HashSet<Student>();  
     for (int i = 0; i < students.length; i++) {  
      tutees.add(students[i]);     
     } 
    }  

    public Set<Student> getTutees() { return Collections.unmodifiableSet(tutees); } 

    public String getName() { return name; } 

} 

Есть ли еще что можно сделать, чтобы сделать этот класс неизменным? Строка уже неизменна, набор возвращается немодифицируемым. Переменные tutees и name являются частными и окончательными. Что еще можно сделать? Если только классы, использующие класс Tutor, были в пакете, я могу изменить конструктор, метод getTutees и метод getName для private-private?Можно ли сделать этот класс более неизменным?

Edit:

Вот класс Student, вопрос попросил меня описать необходимые изменения и сделать Student неизменны. Я прокомментировал оба метода setter, чтобы я мог сделать переменные окончательными. Это единственный способ сделать его по-настоящему неизменным?

public final class Student { 
    private final String name; 
    private final 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

Я думаю, вы можете захотеть этого при просмотре кода ... – Zizouz212

+0

Если 'Student' не изменен, вызывающий код может изменить его позже. Глубоко скопируйте массив. – fukanchik

+0

Модификации строк могут вызвать создание новых строк, вы можете использовать окончательный StringBuffer. – Ashutosh

ответ

3

В незначительной оптимизации, вы можете сделать tutees неизменны, так что даже не может быть изменен в Tutor.

public Tutor(String name, Student[] students) { 
    this.name = name; 
    Set<Student> tuts = new HashSet<>(); 
    for (Student student : students) { 
     tuts.add(student); 
    } 
    this.tutees = Collections.unmodifiableSet(tuts); 
} 
public Set<Student> getTutees() { return this.tutees; } 

Сокращенный вариант: неизменность

public Tutor(String name, Student[] students) { 
    this.name = name; 
    this.tutees = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(students))); 
} 
public Set<Student> getTutees() { return this.tutees; } 
+0

Если ссылки на объекты «Студент» хранятся в другом месте, когда этот объект сконструирован, а экземпляры «Студенты» изменяемы, то этот класс по-прежнему изменен, даже когда вы его написали. Теперь, когда реализация «Студента» может быть пересмотрена, мы можем с уверенностью сказать, что ваш класс неизменен, как написано. – scottb

+1

@scottb True. Невозможно по-настоящему сделать «Tutor» неизменным, если Студент изменчив. И ваш комментарий верен, даже если ссылки «Студент» не хранятся в другом месте, так как ссылку можно получить здесь. – Andreas

2

Вашего класса зависит исключительно от неизменности Student класса. Если Student является неизменным, то Tutor является неизменным и наоборот. Для обеспечения неизменности класса Tutor больше ничего не требуется.

Что касается видимости. Если ваш класс используется только в пакете, make является package-private (на уровне класса). Оставьте общедоступные методы общедоступными.

+0

Неизменяемость условно считается феноменом «все или ничего», но могут быть оттенки серого. Если 'Студент' * является неизменно неизменным * ... или ...существует контракт на выполнение, что ссылка на 'Student []' не должна удерживаться после его добавления в этот класс ... тогда может быть уместно считать класс неизменным. Это касается оберток, таких как Collections.unmodifiableList(). – scottb

+0

@scottb Я соглашаюсь на * эффективно неизменный * 'Студент', не вижу, как он отличается от того, что я сказал. Но когда 'Student' является изменяемым, вы не можете быть уверены, что он не будет мутирован после того, как он будет возвращен методом getTutees', поскольку экземпляры« Student »возвращаются * как есть *, без обертывания или копирования. – Aivean

1

Immutables - удобный инструментарий для создания неизменяемых объектов на Java. Если вы построите свой домен, используя его, он будет неизменным. Из уравнения берется вопрос о том, является ли этот объект неизменным.

 Смежные вопросы

  • Нет связанных вопросов^_^