В Java неизменността означава, че след като обектът е създаден, неговото вътрешно състояние не може да бъде променено. Неизменните класове в Java осигуряват много предимства като безопасност на нишки, лесно отстраняване на грешки и всичко останало. В Java всички обвиващи класове (като Integer Boolean Byte Short) и класът String е неизменен. Можем да създадем и наш собствен неизменен клас.
В тази статия ще научим:
- Какво означава неизменност
- Защо е полезно
- Как да създадем наш собствен неизменен клас
- Защо дълбокото копиране е важно
- Какви са ограниченията, които имат типовете записи на Java
Какво е неизменен клас?
Неизменен клас е клас, чиито обекти не могат да бъдат променяни, след като бъдат създадени. Ако направим някаква модификация, това води до нов обект. Този метод се използва в едновременни приложения.
Правила за създаване на неизменен клас
- Класът трябва да бъде деклариран като окончателен така че да не могат да се създават дъщерни класове.
- Членовете на данните в класа трябва да бъдат декларирани частен така че директният достъп не е разрешен.
- Членовете на данните в класа трябва да бъдат декларирани като окончателен така че да не можем да променим тяхната стойност след създаването на обекта.
- Параметризираният конструктор трябва да инициализира всички полета, изпълняващи a дълбоко копие така че членовете на данните да не могат да бъдат модифицирани с препратка към обект.
- Дълбокото копиране на обекти трябва да се извършва в методите за получаване, за да се върне копие, вместо да се върне действителната препратка към обекта.
Забележка : Не трябва да има сетери или казано по-просто, не трябва да има опция за промяна на стойността на променливата на екземпляра.
Пример: Реализация на неизменен клас
Студент.java
филмова актриса рекаJava
// Java Program to Create An Immutable Class import java.util.HashMap; import java.util.Map; // declare the class as final final class Student { // make fields private and final private final String name; private final int regNo; private final Map<String String> metadata; // initialize all fields via constructor public Student(String name int regNo Map<String String> metadata) { this.name = name; this.regNo = regNo; // deep copy of mutable object (Map) Map<String String> tempMap = new HashMap<>(); for (Map.Entry<String String> entry : metadata.entrySet()) { tempMap.put(entry.getKey() entry.getValue()); } this.metadata = tempMap; } // only provide getters (no setters) public String getName() { return name; } public int getRegNo() { return regNo; } // return deep copy to avoid exposing internal state public Map<String String> getMetadata() { Map<String String> tempMap = new HashMap<>(); for (Map.Entry<String String> entry : this.metadata.entrySet()) { tempMap.put(entry.getKey() entry.getValue()); } return tempMap; } }
В този пример създадохме окончателен клас с име Студент. Той има три крайни члена на данни, параметризиран конструктор и методи за получаване. Моля, обърнете внимание, че тук няма метод за настройка. Също така имайте предвид, че не е необходимо да извършваме дълбоко копиране или клониране на членове на данни от типове обвивки, тъй като те вече са неизменни.
Geeks.java:
Javaimport java.util.HashMap; import java.util.Map; public class Geeks { public static void main(String[] args) { // create a map and adding data Map<String String> map = new HashMap<>(); map.put('1' 'first'); map.put('2' 'second'); // create an immutable Student object Student s = new Student('GFG' 101 map); // accessing data System.out.println(s.getName()); System.out.println(s.getRegNo()); System.out.println(s.getMetadata()); // try to modify the original map map.put('3' 'third'); System.out.println(s.getMetadata()); // try to modify the map returned by getMetadata() s.getMetadata().put('4' 'fourth'); System.out.println(s.getMetadata()); } }
Дори след модифициране на оригиналната или върната карта вътрешното състояние на обекта Student остава непроменено. Това потвърждава концепцията за неизменност.
Изход:
GFG
101
{1=first 2=second}
{1=first 2=second}
{1=first 2=second}
Ограничение на Java запис с променливи полета
Представена е Java 14 запис . Това е ясен и кратък начин за дефиниране на неизменни като класове:
алгоритъм на кабината
запис Student(Име на низ int regNo Карта
метаданни) {}
Но това предлага само плитка неизменност. Ако картата се модифицира външно, вътрешното състояние на записа се променя:
Карта
карта = нова HashMap<>(); map.put('1' 'първи');
Student s = нов ученик ('ABC' 101 карта);
// Променя вътрешното състояние — НЕ е безопасно
map.put('2' 'втори');
s.metadata().put('3' 'трети');
Забележка : Използвайте запис само ако всички полета са неизменни типове като String int или други записи.
как да промените низ на int