I have a case where I want to avoid protective copies, for data that, however, can be changed, but usually just read and write. Thus, I would like to use immutable objects with functional mutator methods, which are commonplace (java lombok is able to do this more or less automatically). I continue with the following:
public class Person { private String name, surname; public Person(String name, String surname) {....}
So, to get a copy of a person with a different name, I would call
p= new Person("Bar", "Alfred"); ... p= p.withName("Foo");
In practice, the objects are quite large (and I ended up using serialization to avoid the burden of writing copy code).
Now, looking at the web interface, I see a potential concurrency problem with this implementation, as my fields are not final, and thus simultaneous access can see the returned copy, for example, without changing the new name (as in this context there is no guarantee on operating procedure).
Of course, I cannot make my fields final, with the current implementation, since I first make a copy and then modify the data in the copy.
So, I am looking for a good solution to this problem.
I can use volatile, but I think this is not a good solution.
Another solution would be to use a builder pattern:
class PersonBuilder { String name, surname; .... } public class Person { private final String name, surname; public Person(PersonBuilder builder) {...} private PersonBuilder getBuilder() { return new PersonBuilder(name, surname); } public Person withName(String name) { PersonBuilder b= getBuilder(); b.setName(name); return new Person(b); } }
Is there a problem here, and above all, is there a more elegant way to do the same?