所有最终类都是不可变的吗?

时间:2009-10-27 11:55:11

标签: java immutability

Java中的所有最终类都是不可变的。 String和Integer都是最终的类,两者都是不可变的,我相信。

8 个答案:

答案 0 :(得分:30)

不,最终意味着该课程无法延期。它没有说明可变性。例如:

final class MutInt {
   public int modifyMe;
}

答案 1 :(得分:22)

不 - 最后一堂课意味着你不能继承它。它与可变性无关。以下课程是最终的,但却是可变的:

public final class FinalMutable {
  int value;
  public void setValue(int v) { value=v; }
  public int getValue() { return value; }
}

答案 2 :(得分:9)

没有关键词的不变性,它更像是一种设计模式。

编辑:
这意味着,没有关键字,这使得一个类不可变。要使类不可变,您必须通过使其成为最终或私有来保护内部。

令人困惑的是:当在类上使用时,final关键字具有不同的含义,然后在字段/变量上使用时具有不同的含义。前者的意思是“这个课程不能延长”。第二个意思是“这个变量(或参考)不能改变”。

答案 3 :(得分:5)

除了其他回复之外,如果您查看java.lang.String的代码,您会看到它包含一个字段:hash可变,实际上是第一次调用hashCode()时计算和存储。

但是,该课程仍然是不可变hash字段无法直接访问或在课程外修改。

另外,您可能会注意到JDK中的一个常见方法是实现不可变包装器,这些包装器可用于公开对象的内部状态而不允许对其进行修改; e.g。

private final List<String> values;

public List<? get String> getValues() {
  return Collections.unmodifiableList(values);
}

答案 4 :(得分:5)

正如其他人在final之前所说的那样,尽管它在不变性策略中起作用,但它并没有在Java中创建一个类。要获得不变性,您应该遵循一般指导原则:

  • 确保无法覆盖类 - 创建类final,或使用静态工厂并使构造函数保持私有
  • 制作字段privatefinal
  • 强制调用者在一个步骤中完全构造一个对象,而不是使用无参数构造函数和后续调用setXXX方法(即,避免Java Beans约定)
  • 不提供任何可以以任何方式改变对象状态的方法 - 不只是setXXX方法,而是任何可以改变状态的方法
  • 如果类有任何可变对象字段,那么在类和调用者之间传递时必须对它们进行防御性复制

答案 5 :(得分:2)

子类的重写方法无法访问私有字段...所以子类方法没有办法改变超类的私有字段...那么将不可变类作为最终用法有什么用呢? ?

答案 6 :(得分:0)

最终关键字会阻止其他类继承它。 Final关键字不会使它成为不可变的,但是有一些条件,例如将实例类成员设为私有,最终使用getter而不是使用setter

答案 7 :(得分:0)

不能更改最终的不可变类。在下面,它显示了一个非最终的不可变类,正在被突变:

// a class not intended to be mutated 
public class GoodClass{

   private String name;

   public GoodClass() {
       this.name = "Good Class Neme";
   }

   public String getName() {
       return name;
   }
}

public class BadClass extends GoodClass {

   private String name;

   public String getName() {
       return name;
   }

   // mutating state
   public void setName(String name) {
       this.name = name;
   }
}