我有一个案例,当我想避免防御性副本,对于可能仍然被修改的数据,但通常只是阅读,而不是写入.所以,我想使用不可变对象,使用函数mutator方法,这是常见的(java lombok能够或多或少地自动执行).我进行的方式如下:
public class Person {
private String name, surname;
public Person(String name, String surname) {....}
// getters...
// and instead of setters
public Person withName(String name) {
Person p= copy(); // create a copy of this...
p.name= name;
return p;
}
public Person copy() {....}
}
Run Code Online (Sandbox Code Playgroud)
因此,要获得具有不同名称的人的副本,我会打电话
p= new Person("Bar", "Alfred");
...
p= p.withName("Foo");
Run Code Online (Sandbox Code Playgroud)
在实践中,对象相当大(我最终使用序列化来避免编写复制代码的负担).
现在,在浏览网页时,我发现这个实现存在潜在的并发问题,因为我的字段不是最终的,因此,并发访问可能会看到返回的副本,例如,没有新的名称更改(因为没有保证在这种情况下的操作顺序).
当然,我无法使用当前实现将我的字段设为最终,因为我先复制,然后更改副本中的数据.
所以,我正在为这个问题寻找一个好的解决方案.
我可能会使用volatile,但我觉得这不是一个好的解决方案.
另一种解决方案是使用构建器模式:
class PersonBuilder {
String name, surname; ....
}
public class Person {
private final String name, surname;
public Person(PersonBuilder …Run Code Online (Sandbox Code Playgroud)