不变的阶级

时间:2013-09-21 11:17:14

标签: java string immutability

我知道如何创建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 一书也说“将您的方法标记为最终,以便不会覆盖”< / strong>。但是,当字段被声明为final以及setter时,我无法理解为什么我需要在课程或private方法上使用final

或者文章和EFFECTIVE JAVA提出了另一种方法!!!

4 个答案:

答案 0 :(得分:2)

制作课程immutable并将课程声明为final具有不同的含义。如果您创建类final,则意味着您无法覆盖方法中的任何功能(方法),这与immutablity不同。 即使您将field作为最终版本,我仍然可以extend class,并覆盖其他方法,例如在您返回的方法getName中{{1}我可以覆盖该方法,我可以使employee name返回method

查看示例:

employee name + employee id

来自Java Doc Strategy for Defining Immutable Objects

public class SubEmployee extends Employee{

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

    }
}

答案 1 :(得分:2)

正如其他人所解释的那样,它可以防止子类改变父类的行为。引用 Effectice Java

  

确保无法扩展课程。这可以防止粗心或   恶意子类破坏了不可变的行为   通过表现就好像对象的状态已经改变一样。预防   子类化通常是通过使类最终完成而完成的   我们将在稍后讨论一种替代方案。

以下是一个例子:

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!?
    }
}

答案 2 :(得分:1)

如果你没有让Employee类或者最后的所有方法结束,我可以编写一个可变的MyEmployee类。然后我可以将它传递给任何需要Employee的方法。如果您的代码依赖于Employee是不可变的这一事实,那么当ID发生变化时会非常惊讶,因为它是一个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;
    }

答案 3 :(得分:0)

首先,您需要了解最终访问和私人访问之间的区别。当您将方法声明为Private时,并不意味着您无法覆盖它。类上的Final关键字使得类不可访问,并且on方法使非覆盖和on变量为常量。最好在setter上使用Final Keyword,以避免使用它的任何其他类的无意更改。