Java不可变类?

sfr*_*frj 18 java

我发现了一篇包含一段有趣代码的文章:

public class Employee {

    private String firstName;
    private String lastName;

    //private default constructor
    private Employee(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public static Employee valueOf (String firstName, String lastName) {
        return new Employee(firstName, lastName);
    }
}
Run Code Online (Sandbox Code Playgroud)

我非常好奇理解创建这种类的优势.我知道这个类的对象是不可变的,因为初始化后无法更改其变量值.我之前从未做过这样的事情,我真的不明白它的优点.

  • 为什么这是一个好习惯?
  • 你能说出一种可以使用这种方法的情况吗?
  • 常量或只读变量怎么样?那不是很相似吗?
  • 在文章中说,这对应用程序的性能不利.但为什么呢?

San*_*osh 19

你提到的例子是一个不可变对象.它在编程语言中被广泛使用的概念.

引用上面的链接.优点是

  • 很容易构建,测试和使用
  • 是自动线程安全的,没有同步问题
  • 不需要复制构造函数
  • 不需要克隆的实现
  • 允许hashCode使用延迟初始化,并缓存其返回值
  • 当用作场时,不需要防御性地复制
  • 制作好的Map键和Set元素(这些对象在集合中不得改变状态)
  • 在建造之后建立他们的阶级不变量,它永远不需要再次检查
  • 总是有"失败原子性"(Joshua Bloch使用的术语):如果一个不可变对象 - 引发异常,它永远不会处于不受欢迎或不确定的状态

  • 我不确定"允许hashCode使用延迟初始化,并缓存其返回值".你的意思是对象的哈希码是在第一次调用它的`hashCode()`方法时计算并存储在一个字段中,之后返回该字段?因为在这种情况下,对象实际上是*不是*不可变的,并且它失去了"自动线程安全"属性.多个线程不能同时安全地调用`hashCode()`,除非他们可以确定该字段之前已经初始化(或者除非你使用`synchronized` /`volatile`/whatnot). (2认同)
  • @jprete:肯定有一些方法,但它们需要明确的行动; 它与真正不可变对象提供的"自动[]线程安全[ty]"完全不同. (2认同)