Относительно неизменного класса защитного копирования

У меня есть вопрос относительно создания неизменяемого класса. Ниже приведены моменты, которые я принимаю во внимание:

  1. Сделать финал класса
  2. Сделайте все члены окончательными, установите их явно, в статическом блоке или в конструкторе
  3. Сделайте всех участников приватными
  4. Нет методов, которые изменяют состояние
  5. Будьте предельно осторожны, чтобы ограничить доступ к изменяемым компонентам-членам (помните, что поле может быть окончательным, но объект все еще может быть изменяемым. Например, закрытое конечное значение Date imStillMutable). См. Защитное копирование или конструкторы его двоюродных копий для получения дополнительной информации.


Но я не совсем понял 5 баллов, не могли бы вы посоветовать или показать мне пример, в котором 5 баллов ясно в этом примере?

2 ответа

Решение

Пункт 5 предполагает, что всякий раз, когда у вас есть какие-либо методы, которые возвращают что-то, связанное с изменяемым объектом, вы захотите создать копию, независимую от частного состояния. Например:

public final class Foo
{
    private final List<String> strings;

    public Foo(List<String> strings)
    {
        // Defensive copy on construction. Protects from constructing
        // code mutating the list.
        this.strings = new ArrayList<String>(strings);
    }

    public List<String> getStrings()
    {
        // Defensive copy on read. Protects from clients mutating the list.
        return new ArrayList<String>(strings);
    }
}

Обратите внимание, что защитное копирование требуется только в том случае, если состояние изменчиво. Например, если вы использовали ImmutableList (например, из Гуавы) в качестве состояния в вышеприведенном классе, вам нужно будет создать новый список в конструкции (если вход не является также ImmutableList) но не в getStrings,

Также обратите внимание, что в этом случае String является неизменным, поэтому нам не нужно копировать каждую строку. Если бы это было List<StringBuilder> нам нужно создать новый список и новую копию каждого элемента как часть защитной копии. Как видите, жизнь становится проще, когда все ваше состояние тоже неизменно.

final означает, что указатель не может указывать на другую ссылку. Например:

final Object obj = new Object();
obj = new Object(); //Invalid

Но final не мешает модификации объекта:

obj.setWhatever("aaa"); //Perfectly valid

Если вы не ограничили доступ к членам, то любой может получить объект и изменить его.

Например: yourClass.getObject().setWhatever("aaa").

Защитное копирование означает, что getObject() не вернет объект напрямую, но создаст его копию и вернет. Таким образом, если вызывающая сторона изменяет возвращаемый объект, она не будет изменять исходный член класса.

Другие вопросы по тегам