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,甚至Effective JAVA书都说“将您的方法标记为最终的,这样它们就不会被覆盖”。但是我不明白为什么我需要final在类或setter方法上使用,当字段被声明privatefinal

或者文章和 EFFECTIVE JAVA 建议另一种方法!

4

4 回答 4

2

创建类immutable和声明类final具有不同的含义。如果您创建类final,则意味着您不能覆盖方法中的任何功能(方法),这与immutablity. 即使您将fieldas final 设置为最终,我仍然可以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.
于 2013-09-21T11:43:56.650 回答
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!?
    }
}
于 2013-09-21T11:48:47.473 回答
1

如果您不将 Employee 类设置为 final 或将其上的所有方法设置为 final,我可以编写一个可变的 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;
    }
于 2013-09-21T11:51:32.770 回答
0

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

于 2013-09-21T11:22:22.437 回答