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
Отличная статья, жду еще
ОтветитьУдалитьСпасибо, если интересует какая-то определенная тема, поделись, возможно, о ней напишу)
Удалить