简体   繁体   English

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

[英]Are all final class immutable?

Are all final classes in Java immutable. Java中的所有最终类都是不可变的。 String and Integer both are final classes and both are immutable i beleive. String和Integer都是最终类,两者都是不可变的。

No, final means the class can not be extended. 不,最终意味着课程无法延期。 It says nothing about mutability. 它没有说明可变性。 For example: 例如:

final class MutInt {
   public int modifyMe;
}

No - a final class means you cannot inherit from it. 不 - 最后一堂课意味着你不能从中继承。 It has nothing to do with mutability. 它与可变性无关。 The following class is final yet mutable: 以下类是最终的可变的:

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

There is no keyword for immutability, it's more like a design pattern. 不可变性没有关键字,它更像是一种设计模式。

EDIT: 编辑:
This means, there is no keyword, that makes a class immutable. 这意味着,没有关键字,这使得一个类不可变。 To make a class immutable, you have to protect the internals by make them final or private. 要使类不可变,您必须通过将它们设为final或private来保护内部。

The confusing thing is this: The final keyword has different meanings when used on a class then it has when used on a field/variable. 令人困惑的是:final关键字在类上使用时具有不同的含义,然后在字段/变量上使用时具有不同的含义。 The former means "this class can not be extended". 前者的意思是“这个课程不能延长”。 The Second means "this variable (or reference) can not be changed". 第二个意思是“这个变量(或参考)不能改变”。

Further to the other responses, if you look at the code for java.lang.String you'll see it contains a field: hash , which is mutable and is in fact computed and stored when hashCode() is called for the first time. 除了其他响应,如果你看一下java.lang.String的代码,你会看到它包含一个字段: hash ,它是可变的,实际上是在第一次调用hashCode()时计算和存储的。

However, the class is still immutable : The hash field cannot be accessed directly or modified outside of the class. 但是,该类仍然是不可变的hash字段不能直接访问或在类外修改。

Also, you may notice a common approach within the JDK is the implementation of immutable wrappers that can be used to expose an object's internal state without allowing it to be modified; 此外,您可能会注意到JDK中的一个常见方法是实现不可变包装器,这些包装器可用于公开对象的内部状态而不允许对其进行修改; eg 例如

private final List<String> values;

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

As has been said by the others before final does not make a class imuutable in Java though it plays a part in the immutability strategy. 正如其他人所说的那样,尽管它在不变性战略中发挥作用,但final并没有在Java中创造出一个可以用来改进的类。 To obtain immutability you should follow the general guidlines: 要获得不变性,您应该遵循一般指导原则:

  • ensure the class cannot be overridden - make the class final , or use static factories and keep constructors private 确保不能覆盖类 - 使类final ,或使用静态工厂并保持构造函数私有
  • make fields private and final 将字段设为privatefinal
  • force callers to construct an object completely in a single step, instead of using a no-argument constructor combined with subsequent calls to setXXX methods (that is, avoid the Java Beans convention) 强制调用者完全在一个步骤中构造一个对象,而不是使用无参数构造函数和后续调用setXXX方法(即避免Java Beans约定)
  • do not provide any methods which can change the state of the object in any way - not just setXXX methods, but any method which can change state 不提供任何可以以任何方式改变对象状态的方法 - 不仅仅是setXXX方法,而是任何可以改变状态的方法
  • if the class has any mutable object fields, then they must be defensively copied when passed between the class and its caller 如果类具有任何可变对象字段,则在类和调用者之间传递时必须对它们进行防御性复制

子类的重写方法无法访问私有字段...因此子类方法无法更改超类的私有字段...那么将不可变类作为final是什么用途?

Final keywords prevents the other classes to inherit it. 最终关键字阻止其他类继承它。 Final keyword doesn't make it immutable but there are such condition as making the instance class members private as well final and by using getters and not using setters Final关键字不会使它成为不可变的,但是存在这样的条件:将实例类成员设为私有,最终使用getter而不使用setter

A final immutable classes cannot be mutated. 最终的不可变类不能变异。 Here below it shows a non-final immutable class being mutated: 下面显示了一个非最终的不可变类被突变:

// 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;
   }
}



声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM