Свойство за неизменност в java

Знам, че когато става въпрос за предаване на обекти в java, референцията на обекта се предава като стойност. Така че всички промени, които правите в този обект, се отразяват и в оригиналния обект. За да избегнем това, ние използваме свойството immutability в java.

Въпросът ми е, че създадох неизменен клас Employee, когато предам обект от този Employee клас на някакъв метод в друг клас, не искам този метод да прави промени в този обект . Дори и да го направи, не искам промените да бъдат засегнати в оригиналния обект, създаден в извикващия клас.

Ето моя примерен код.

public final class Employee {
    int employeeId;

    public int getId() {
        return employeeId;
    }

    public void setId(int id) {
        this.employeeId = id;
    }

}

public class Worker {
    public static void process(Employee f, Employee g){
        int c = f.getId();
        f.setId(g.getId());
        g.setId(c);
    }
}

public class ImmutabilityTest{

    public static void main(String[] args) {
        Employee teamMember = new Employee();
        Employee teamLead = new Employee();
        teamMember.setId(5);
        teamLead.setId(10);
        System.out.println("Before process "+teamMember.getId() + " " + teamLead.getId());
        Worker.process(teamMember, teamLead);
        System.out.println("After process "+teamMember.getId() + " " + teamLead.getId());
    }
}

Резултатът ще бъде

Before process 5 10
After process 10 5

Има ли някакъв начин да се избегне промяната в стойностите на членските променливи на класа Employee? (освен да ги направим final) Ако не, тогава как всъщност използваме свойството Immutability в java в дефиниран от потребителя клас?

Всички предложения/мнения/насоки се оценяват! Благодаря..


person Rakesh    schedule 21.03.2012    source източник


Отговори (5)


Неизменността не е свойство в Java, което може да се приложи към обект с една ключова дума, това е стратегия, която трябва да се прилага за всеки отделен случай. Най-общо казано, вие използвате ключовата дума final и клониране, за да постигнете това. Обърнете внимание, че колкото по-дълбоко е влагането на вашия обект, толкова по-голямо е нивото на трудност при постигането на истинска неизменност на обекта.

Ето една (по-) неизменна версия на вашия клас Employee:

public class Employee {
    final int employeeId;

    public Employee(final int id) {
        super();
        this.employeeId = id;
    }

    public int getId() {
        return employeeId;
    }
}

Обърнете внимание, че отражението в Java прави практически невъзможно постигането на истинска неизменност, дори с използването на променливи на крайния екземпляр и клониране.

person Perception    schedule 21.03.2012

Employee има сетер и има нечастно поле, следователно не е неизменен.

Премахнете сетера и направете полето private и проблемът ви е решен.

Другата ви опция е да подадете копие на обекта (обикновено с помощта на конструктор за копиране, за да го създадете)

person Bohemian♦    schedule 21.03.2012
comment
дори и да премахна сетера, няма разлика. Все още мога да променя стойността като teamMember.id=15 - person Rakesh; 21.03.2012

Прилагането на ключовата дума final към клас просто показва, че класът не може да бъде разширен (или подклас).

Няма нищо общо с това дали неговите членове могат да бъдат модифицирани или не.

person jahroy    schedule 21.03.2012
comment
+1: Благодаря за корекцията, обърках се с класа String, който е окончателен и неизменен!! :-) - person Rakesh; 21.03.2012

Можете да промените видимостта на метода setId, за да бъде частен пакет, и да се уверите, че Worker е в различен пакет от Employee.

Като алтернатива премахнете изцяло метода setId.

[Ако другият клас прави промени] Не искам промените да бъдат засегнати в оригиналния обект, създаден в извикващия клас.

Ако искате да приемете този подход, тогава трябва да създадете и подадете копие на оригиналния обект.


Обърнете внимание, че освен ако не декларирате частното поле employeeId като final, няма да получите пълната полза от неизменността. Строго погледнато, методът getId трябва да бъде синхронизиран, ако има някаква възможност различни нишки да извикат getId на едно и също Employee копие.

person Stephen C    schedule 21.03.2012

Ако не искате някой да промени стойността на вашите свойства, можете да ги запазите като лични без настройка.

person kundan bora    schedule 21.03.2012