суббота, 23 января 2016 г.

Неизменяемые классы


Immutable classes in Java

Ha четырех собеседованиях из пяти вас спросят о Immutable classes (неизменяемые классы). Хотя вопрос простой, ответить без подготовки на него непросто.

В этой статье мы рассмотрим пример неизменяемого класса из JDK в деталях, который позволит нам понять эту концепцию.

String


public final class String
    implements java.io.Serializable, Comparable, CharSequence

  • Первый момент, который мы видим - обозначить класс как final, если класс не может быть унаследован, то и поведение его методов нельзя переопределить


    /** The value is used for character storage. */
    private final char value[];

    ...

    /**
     * Initializes a newly created {@code String} object so that it represents
     * an empty character sequence.  Note that use of this constructor is
     * unnecessary since Strings are immutable.
     */
    public String() {
        this.value = new char[0];
    }

    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }

  • Все поля класса должны быть final и в таком случае их инициализация будет происходить через конструктор.
  • Следующий важный момент - это конструктор, незменяемый класс не должен предоставлять конструктор без аргумента. Неизменяемый объект должен получать свое состояние через конструктор. Если вы не передаете состояние, то зачем вам объект? Тем не менее в String мы видим пустой коструктор, но к нему идет соответствующий комментарий - Note that use of this constructor is unnecessary since Strings are immutable.
  • Предоставьте хотя бы один коструктор - это ваш последний шанс передать состояние


    public String concat(String str) {
        int otherLen = str.length();
        if (otherLen == 0) {
            return this;
        }
        int len = value.length;
        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);
        return new String(buf, true);
    }

  • Не предоставляйте методов, которые могут изменить состояние объекта (это касается не только геттеров/сеттеров) - методов возращающих ссылки на изменяемые объекты. Убедитесь, что вы безопасно скопировали ссылки изменяемого объекта (в примере, хорошо изместный метод concat это видно из Arrays.copyOf(value, len + otherLen), где мы создаем новый массив, копируя текущий)
  • Если вы возвращаете объект, используйте clone, коллекцию - Collections.unmodified[type of collection]


Эта та стратегия, котороя поможет сделать ваш класс Immutable

Используемый материал

2 комментария:

  1. Ответы
    1. Спасибо, если интересует какая-то определенная тема, поделись, возможно, о ней напишу)

      Удалить