14

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

4

8 回答 8

30

不,final 意味着类不能扩展。它没有提到可变性。例如:

final class MutInt {
   public int modifyMe;
}
于 2009-10-27T11:57:01.980 回答
22

不——最终类意味着你不能从它继承。它与可变性无关。以下类是最终的但可变的:

public final class FinalMutable {
  int value;
  public void setValue(int v) { value=v; }
  public int getValue() { return value; }
}
于 2009-10-27T11:57:31.740 回答
9

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

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

令人困惑的是:final 关键字在用于类时与在字段/变量上使用时具有不同的含义。前者的意思是“这个类不能扩展”。第二个意思是“这个变量(或引用)不能改变”。

于 2009-10-27T11:58:51.210 回答
5

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

但是,该类仍然是不可变的:该hash字段不能在类之外直接访问或修改。

此外,您可能会注意到 JDK 中的一种常见方法是实现不可变包装器,该包装器可用于公开对象的内部状态而不允许对其进行修改;例如

private final List<String> values;

public List<? get String> getValues() {
  return Collections.unmodifiableList(values);
}
于 2009-10-27T12:09:34.987 回答
5

正如其他人之前所说的final那样,尽管它在不变性策略中发挥了作用,但它并没有使 Java 中的类成为不可变的。要获得不变性,您应该遵循一般准则:

  • 确保类不能被覆盖-创建类final,或使用静态工厂并保持构造函数私有
  • 制作字段privatefinal
  • 强制调用者在一个步骤中完全构造一个对象,而不是使用无参数构造函数与对setXXX方法的后续调用相结合(即避免 Java Beans 约定)
  • 不提供任何可以以任何方式改变对象状态的方法——不仅仅是setXXX方法,而是任何可以改变状态的方法
  • 如果类有任何可变对象字段,那么当在类和它的调用者之间传递时,它们必须被防御性地复制
于 2009-10-27T15:46:47.583 回答
2

子类的重写方法无法访问私有字段……所以子类方法无法更改超类的私有字段……那么将不可变类设为final有什么用?

于 2011-07-26T16:25:40.100 回答
0

final 关键字防止其他类继承它。Final 关键字不会使其不可变,但有这样的条件,例如使实例类成员私有以及 final 以及使用 getter 而不是使用 setter

于 2012-06-05T07:58:16.247 回答
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;
   }
}



于 2019-02-05T03:07:25.573 回答