Благодаря этому руководству вы узнаете, что такое неизменяемость (неизменность) в Java и как создать неизменяемый класс в Java.
Неизменяемость (Immutability) в Java — это состояние, в котором значение объектов нельзя изменить после их инициализации.
В Java примитивные классы float, int, long, double, все устаревшие классы, классы-оболочки, классы String и другие являются неизменяемыми.
- Неизменяемый класс хорошо применять для кэширования, поскольку вам не нужно беспокоиться об изменении значения.
- Неизменяемый класс по своей сути потокобезопасен, поэтому вам не нужно беспокоиться о безопасности потоков в многопоточных средах.
String testImmutability = "String Not Immutable";
testImmutability.concat("---");
System.out.println(testImmutability);
// Это будет успешно объединено, так как будет создан новый объект String
String concat = testImmutability.concat("---");
System.out.println(concat);
// Вывод
String Not Immutable
String Not Immutable---
Этапы создания собственного неизменяемого класса:- Объявите класс как final, чтобы его нельзя было расширить.
- Сделайте все поля private, чтобы прямой доступ был запрещен.
- Не предоставляйте методы setter для переменных.
- Сделайте все изменяемые поля final, чтобы значение поля можно было назначить только один раз.
- Инициализируйте все поля с помощью метода конструктора, выполняющего глубокое копирование.
- Выполните клонирование объектов в методах getter, чтобы возвращать копию, а не реальную ссылку на объект.
final class ImmutableClassExample {
private final Map<String, String> dataMap;
private final String name;
private final String id;
// Делаем глубокую копию в конструкторе
public ImmutableClassExample(String name, String id, Map<String, String> dataMap) {
this.name = name;
this.id = id;
Map<String, String> tempMap = new HashMap<>();
for (Map.Entry<String, String> entry : dataMap.entrySet()) {
tempMap.put(entry.getKey(), entry.getValue());
}
this.dataMap = tempMap;
}
// Делаем глубокую копию в геттере
public Map<String, String> getDataMap() {
Map<String, String> tempMap = new HashMap<>();
for (Map.Entry<String, String> entry : dataMap.entrySet()) {
tempMap.put(entry.getKey(), entry.getValue());
}
return tempMap;
}
public String getName() {
return name;
}
public String getId() {
return id;
}
}
public class Test {
public static void main(String args[]) {
Map<String, String> map = new HashMap<>();
map.put("1", "One");
map.put("2", "Two");
ImmutableClassExample s = new ImmutableClassExample("ABC", "101", map);
System.out.println(s.getName());
System.out.println(s.getId());
System.out.println(s.getDataMap());
map.put("3", "third");
// Не изменится из-за глубокого копирования в конструкторе
System.out.println(s.getDataMap());
s.getDataMap().put("4", "fourth");
// Раскомментирование следующего кода вызовет ошибку, так как мы пытаемся получить доступ к члену private
// s.id = "4";
}
}
// Раскомментирование следующего кода вызовет ошибку, так как мы пытаемся наследовать класс final); } } */
/*
class CheckInheritance extends ImmutableClassExample{
public CheckInheritance(String name, String id, Map<String, String> dataMap) {
super(name, id, dataMap);
}
}
*/
Вывод:
ABC
101
{1=One, 2=Two}
{1=One, 2=Two}
Помните, что в коде не должно быть методов setter, чтобы не было возможности изменить данные.
Интересные факты
Метод создания неизменяемого класса в Java широко используется в версиях до Java 14. Проблема с приведенным выше решением заключается в том, что оно создает много шаблонного кода и допускает ошибки. В Java 14 появились записи (Records), которые можно использовать для создания неизменяемых объектов “только для чтения”. Записи представляют собой неизменяемую структуру данных, поэтому они более предпочтительны и должны использоваться вместо создания неизменяемых классов. Одним из важных аспектов записей является то, что поля final не могут быть перезаписаны с помощью отражения (reflection). Вот как выглядит приведенный ранее пример с использованием записей:
record ImmutableClassExample(String name, String id, Map<String, String> dataMap) {
}
Надеюсь, эта публикация вам поможет в вашей работе! Удачного кодирования!
Источник: Medium
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ