Як створити незмінний клас у Java?
У Java незмінність означає, що після створення об’єкта його внутрішній стан не можна змінити. Незмінні класи в Java надають багато переваг, наприклад безпеку потоків, просте налагодження тощо. На Java все класи-обгортки (наприклад, Integer Boolean Byte Short), а клас String є незмінним. Ми також можемо створити свій власний незмінний клас.
У цій статті ми дізнаємося:
- Що означає незмінність
- Чому це корисно
- Як створити наш власний незмінний клас
- Чому глибоке копіювання важливо
- Які обмеження мають типи записів Java
Що таке незмінний клас?
Незмінний клас — це клас, створені об’єкти якого неможливо змінити. Якщо ми робимо будь-які зміни, це призводить до нового об’єкта. Цей метод використовується в паралельних програмах.
Правила створення незмінного класу
- Клас повинен бути оголошений як остаточний так що дочірні класи не можуть бути створені.
- Члени даних у класі повинні бути оголошені приватний щоб прямий доступ був заборонений.
- Члени даних у класі мають бути оголошені як остаточний щоб ми не могли змінити їх значення після створення об’єкта.
- Параметризований конструктор повинен ініціалізувати всі поля, що виконують a глибока копія щоб члени даних не могли бути змінені за допомогою посилання на об’єкт.
- Глибоке копіювання об’єктів має виконуватися в методах отримання, щоб повертати копію, а не повертати фактичне посилання на об’єкт.
Примітка : Не повинно бути сеттерів або, простіше кажучи, не повинно бути можливості змінити значення змінної екземпляра.
Приклад: реалізація незмінного класу
Student.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:
Java import 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(String name int regNo Map
метадані) {}
Але це лише пропонує неглибоку незмінність. Якщо карту змінено ззовні, внутрішній стан запису змінюється:
Карта
map = нова HashMap <>(); map.put('1' 'перший');
Student s = new Student('ABC' 101 map);
// Змінює внутрішній стан — НЕбезпечно
map.put('2' 'другий');
s.metadata().put('3' 'третій');
Примітка : використовуйте запис, лише якщо всі поля є незмінними типами, наприклад String int або інші записи.