不变的课程?

Jav*_*ser 81 java string immutability

如何使Java类不可变,对不可变性的需求是什么,使用它有什么好处?

coo*_*ird 128

什么是不可变对象?

不可变对象是在实例化后不会改变状态的对象.

如何使对象不可变?

通常,可以通过定义一个没有暴露任何成员的类,并且没有任何setter来创建不可变对象.

以下类将创建一个不可变对象:

class ImmutableInt {
  private final int value;

  public ImmutableInt(int i) {
    value = i;
  }

  public int getValue() {
    return value;
  }
}
Run Code Online (Sandbox Code Playgroud)

如在上面的例子中可以看出,的值ImmutableInt只能当对象被实例化设置,并且通过仅具有吸气剂(getValue)对象的状态不能实例化之后被改变.

但是,必须要小心采取由该对象引用的所有对象必须是不可变的为好,或者它可能是能够改变对象的状态.

例如,允许对数组的引用或ArrayList通过getter获取将允许通过更改数组或集合来更改内部状态:

class NotQuiteImmutableList<T> {
  private final List<T> list;

  public NotQuiteImmutableList(List<T> list) {
    // creates a new ArrayList and keeps a reference to it.
    this.list = new ArrayList(list); 
  }

  public List<T> getList() {
    return list;
  }
}
Run Code Online (Sandbox Code Playgroud)

上述代码的问题在于,ArrayList可以通过getList并被操纵来获得,导致对象本身的状态被改变,因此,不是不可变的.

// notQuiteImmutableList contains "a", "b", "c"
List<String> notQuiteImmutableList= new NotQuiteImmutableList(Arrays.asList("a", "b", "c"));

// now the list contains "a", "b", "c", "d" -- this list is mutable.
notQuiteImmutableList.getList().add("d");
Run Code Online (Sandbox Code Playgroud)

解决此问题的一种方法是从getter调用时返回数组或集合的副本:

public List<T> getList() {
  // return a copy of the list so the internal state cannot be altered
  return new ArrayList(list);
}
Run Code Online (Sandbox Code Playgroud)

不变性的优势是什么?

不可变性的优势在于并发性.在可变对象中难以保持正确性,因为多个线程可能试图改变同一对象的状态,导致一些线程看到同一对象的不同状态,这取决于对所述读取和写入的时间.宾语.

通过拥有一个不可变对象,可以确保查看该对象的所有线程都将看到相同的状态,因为不可变对象的状态不会改变.

  • 班级也必须成为"最终的".否则,可以使用setter方法(或其他类型的变异方法和可变字段)进行扩展. (17认同)
  • 您还可以"返回Collections.unmodifiableList(list);"以返回列表中的只读视图,而不是返回列表的副本. (5认同)
  • @AbhinavSarkar如果类只有`private`字段,则不必是`final`,因为它们无法从子类访问. (5认同)
  • 线程安全(对于并发很重要)并不是不可变性的唯一优势; 它还意味着你不必制作对象的防御性副本,它可以防止错误,因为你不能错误地修改那些不应该被修改的对象. (4认同)
  • @icza类必须是final,因为我们有公共getter方法,我们可以扩展类并覆盖getter方法,然后以我们的方式更改字段.所以它不再是不可变的 (3认同)

Fab*_*eeg 18

除了已经给出的答案之外,我还建议阅读有效Java,第二版中的不变性,因为有些细节很容易被遗漏(例如防御性副本).另外,有效的Java第二版.是每个Java开发人员必读的.

  • 这是要查看的确切资源.提到的好处范围从容易出错的代码到线程安全. (3认同)

duf*_*ymo 6

你创建了一个类不可变的类:

public final class Immutable
{
    private final String name;

    public Immutable(String name) 
    {
        this.name = name;
    }

    public String getName() { return this.name; } 

    // No setter;
}
Run Code Online (Sandbox Code Playgroud)

以下是使Java类不可变的要求:

  • 必须声明为final(因此无法创建子类)
  • 必须将类中的成员声明为final(因此在创建对象后我们无法更改它的值)
  • 为其中的所有变量编写Getter方法以获取Members
  • 没有Setters方法

不可变类很有用,因为
它们是线程安全的.
- 他们还对你的设计表达了深刻的东西:"不能改变它.",当它适用时,它正是你所需要的.


Jac*_*ack 5

不可变性主要有两种方式:

  • 使用final实例属性来避免重新分配
  • 使用类接口,它只是不允许任何能够修改类内部的操作(只是getter而不是setter

不变性的优点是您可以对这些对象做出的假设:

  • 你获得了无副作用规则(在函数式编程语言中非常流行),并且允许你更容易地在并发环境中使用对象,因为你知道它们不能以原子或非原子的方式被改变.许多线程使用
  • 语言的实现可以以不同的方式处理这些对象,将它们放在用于静态数据的内存区域中,从而更快,更安全地使用这些对象(这是JVM中为字符串发生的事情)