2013-09-21 3 views
1

Я знаю, как создать immutable class. Я создал следующее.Неизменяемый класс

public class Employee { 

    private final int id; 
    private final String name; 
    private final int salary; 

    public Employee(int id, String name, int salary) { 
     this.id = id; 
     this.name = name; 
     this.salary = salary; 
    } 

    public int getId() { 
     return id; 
    } 

    public String getName() { 
     return name; 
    } 

    public int getSalary() { 
     return salary; 
    } 
} 

Несколько статей также предполагает, что вы объявляете свой класс как final, даже Эффективная JAVA книга говорит «пометить методы, как окончательный, так что они не могут быть overriddden». Но я не могу понять, почему мне нужно использовать final по классу или по методам setter, когда поля объявлены private, а также final?

Или изделия и ЭФФЕКТИВНЫЕ JAVA, предлагающие альтернативный подход !!!

ответ

2

Как объяснено другими, его предотвратить подклассы от изменения поведения родительского класса. Цитирование Effectice Java

Убедитесь, что класс не может быть продлен. Это предотвращает небрежное или вредоносные подклассы от компрометации неизменяемого поведения класса , поскольку он ведет себя так, как если бы состояние объекта изменилось. Предотвращение подкласс обычно выполняется путем создания класса final, но есть альтернатива, которую мы обсудим позже.

Вот пример:

public class Manager extends Employee { 

    public Manager(int id, String name, int salary) { 
     super(id, name, salary); 
    } 

    @Override 
    public String getName() { 
     return "doppelganger"; 
    } 

    public static void main(String[] args) { 
     Employee e = new Manager(0, "Eric", 100); //e should be immutable right! 
     System.out.println(e.getName()); // prints "doppelganger", I thought employee was immuatble!? 
    } 
} 
0

Прежде всего вам нужно понять разницу между конечным и частным доступом. Когда вы объявляете метод Private, это не значит, что вы не можете его переопределить. Конечное ключевое слово в классе делает класс недоступным и по методу делает non overridden и переменным в качестве констант. Хорошо использовать Final Keyword для сеттеров, чтобы избежать непреднамеренных изменений от любых других классов, которые его используют.

+0

Можете ли вы привести пример кода, в котором вы можете переопределить частный метод? частные члены не наследуются, и я не думаю, что переопределение возможно. Пожалуйста, поделитесь примером кода. – HakunaMatata

+0

К сожалению, классы, объявленные окончательными, иногда сложнее для модульного теста. Не все модульные тестовые среды могут эффективно высмеивать окончательный класс, а переопределяющие методы, которые затрудняют ваш тест, также практически невозможны. final особенно раздражает старый код, который не тестируется junit ... – extraneon

2

Выполнение класса immutable и объявление класса final имеет различное значение. Если вы сделаете класс final, это означает, что вы не можете переопределить какую-либо функциональность (методы) в ваших методах, которая отличается от immutablity. Даже если вы сделаете field как окончательный, я все еще могу extend ваши class, и переопределить другие методы, скажем, например, в вашем методе getName вы возвращаете employee name, я могу переопределить метод и я могу сделать method возвращается employee name + employee id.

Смотрите пример:

public class SubEmployee extends Employee{ 

public String getName(){ 
    return "Darth Vader"; 

    } 
} 

От Java Doc Strategy for Defining Immutable Objects

Don't allow subclasses to override methods. The simplest way to do 
this is to declare the class as final. A more sophisticated approach is to make the 
constructor private and construct instances in factory methods. 
1

Если вы не сделаете класс Employee окончательный или все методы на нем окончательное, я могу написать класс MyEmployee, которое изменчиво. Затем я могу передать его любому методу, который принимает Employee. Если ваш код зависит от того, что Employee неизменен, он будет очень удивлен, когда идентификатор изменится, потому что это MyEmployee, а не только Employee.

public class MyEmployee extends Employee { 

    private final int id; 

    public MyEmployee(int id, String name, int salary) { 
     super(id, name, salary); 
     this.id = id; 
    } 

    public int getId() { 
     return this.id; 
    } 

    public void setId(final int id) { 
     this.id = id; 
    } 
Смежные вопросы