logo

Како направити непроменљиву класу у Јави?

У Јави непроменљивост значи да када се објекат креира, његово унутрашње стање не може да се промени. Непроменљиве класе у Јави пружају многе предности као што је сигурност нити, лако отклањање грешака и све остало. У Јави све класе омотача (као Интегер Боолеан Бите Схорт) и класа Стринг је непроменљива. Можемо креирати и сопствену непроменљиву класу.

У овом чланку ћемо научити:

  • Шта значи непроменљивост
  • Зашто је корисно
  • Како да створимо сопствену непроменљиву класу
  • Зашто је дубоко копирање важно
  • Која ограничења имају типови Јава записа

Шта је непроменљива класа?

Непроменљива класа је класа чији објекти се не могу мењати када се једном креирају. Ако урадимо било какву модификацију, то резултира новим објектом. Овај метод се користи у истовременим апликацијама.



Правила за креирање непроменљиве класе

  • Класа мора бити декларисана као коначни тако да се дечје класе не могу креирати.
  • Чланови података у класи морају бити декларисани приватни тако да директан приступ није дозвољен.
  • Чланови података у класи морају бити декларисани као коначни тако да не можемо да променимо њихову вредност након креирања објекта.
  • Параметризовани конструктор треба да иницијализује сва поља која изводе а дубока копија тако да чланови података не могу да се мењају помоћу референце објекта.
  • Дубинско копирање објеката требало би да се изврши у методама геттера да би се вратила копија уместо да се врати стварна референца објекта.

Напомена : Не би требало да постоје сеттери или једноставније речено не би требало да постоји опција за промену вредности променљиве инстанце.


Пример: имплементација непроменљиве класе

Студент.јава

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;  } } 

У овом примеру смо креирали коначну класу под називом Студент. Има три коначна члана података, параметризовани конструктор и методе добијања. Имајте на уму да овде не постоји метода подешавања. Такође имајте на уму да не морамо да вршимо дубинско копирање или клонирање чланова података типова омота јер су они већ непроменљиви.

Геекс.јава:

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());   } } 

Чак и након измене оригиналне или враћене мапе унутрашње стање студентског објекта остаје непромењено. Ово потврђује концепт непроменљивости.

Излаз:

GFG  
101
{1=first 2=second}
{1=first 2=second}
{1=first 2=second}


Ограничење Јава записа са променљивим пољима

Представљена је Јава 14 рекорд . Ово је јасан и концизан начин да дефинишете непроменљиве попут класа:

запис Студент(име стринга инт регНо Мапметаподаци) {}


Али ово нуди само плитку непроменљивост. Ако је мапа измењена споља, интерно стање записа се мења:

Мапамап = нова ХасхМап<>();

мап.пут('1' 'први');


Студент с = нови Студент('АБЦ' 101 мапа);


// Мења унутрашње стање — НИЈЕ безбедно

јава маин

мап.пут('2' 'други');

с.метадата().пут('3' 'трећи');

Напомена : Користите запис само ако су сва поља непроменљиви типови као што су Стринг инт или други записи.