Can we treat an object as immutable if we document its immutability
Can we treat an object as immutable if we document its immutability
For instance, I've got this:
public class Container{ private final List strs; /** * Contructs {@code Container} by a given {@code List} * The content of the list referenced should not be modified * after the constructor invocation. */ public Container(List strs){ this.strs = strs; } //Other staff }
The state of Container
could be modified after its construction, but we prohibit in the documentation. Can the object be treated as immutable? Making copy within the constructor is not exactly desirable.
The immutability is for thread-safety sakes.
Answer by slartidan for Can we treat an object as immutable if we document its immutability
You should in general not expose internal structures of classes to the outside. This is espacially important for imutables.
Therefore I suggest to make a copy with new ArrayList(x)
in your constructor.
In addition you can use Collections.unmodifiableList()
to prevent modifications from inside your class.
I suggest the combination of both, which will look like this:
import java.util.Collections; ... public Container(List strs){ this.strs = Collections.unmodifiableList(new ArrayList<>(strs)); }
Your container will remember the members of the list at the time of the call of the constructor. If the list is changed somewhere else, it will not have any effect on your imutable.
Even the code within the container will not be able to modify the list - the list would throw an UnsupportedOperationException
instead.
The complete, working example code:
import java.util.ArrayList; import java.util.Collections; import java.util.List; public class X { public static void main(String[] args) { // create a list List myList = new ArrayList<>(); myList.add("a"); myList.add("b"); // hand it over to the container Container container = new Container(myList); // modify it afterwards myList.add("BUH!"); // check contents of container for (String item : container.strs) { System.out.println(item); } } } class Container{ final List strs; /** * Contructs {@code Container} by a given {@code List} * The content of the list referenced should not be modified * after the constructor invokation. */ public Container(List strs){ this.strs = Collections.unmodifiableList(new ArrayList<>(strs)); } //Other staff }
it outputs:
a b
(does not output BUH!
)
Answer by Daniel Pereira for Can we treat an object as immutable if we document its immutability
You can just document it to improve performance, but I'd only recommend that approach for non-public APIs. In my company we built a framework and manage to take off some of these protections to boost performance/decrease memory usage, but only in code that was internal. We decided to assume that the framework developers wouldn't mess around and it worked well.
If your API is going to be exposed to other developers outside you should always be safe, specially for security reasons. If you really need to improve performance/memory usage, it is an option, but apply it carefully.
Answer by Raedwald for Can we treat an object as immutable if we document its immutability
In general, no. An immutable object can be safely shared between threads. An object being safe to share between threads is not a mere matter of documentation; its class must be implemented in a specific way. Say "objects of this class are immutable" without an implementation that made it immutable would be actively misleading, an untruth, and should be treated as a bug.
Answer by Adi Levin for Can we treat an object as immutable if we document its immutability
If you don't want to copy the list, and still you want it to be really immutable, you can use a persistent data structure such as the ones in Clojure.
In Clojure, all values are immutable, so you can always pass them around safely. When someone adds an item to the front of a list, this logically creates a new list, but actually it only adds a single element that points to the head of the old list, without having to copy all of the previous list. All data structures in Clojure are like that, and you can also use them in Java (see also what's a good persistent collections framework for use in java?).
Or, you can use pcollections.
Answer by wero for Can we treat an object as immutable if we document its immutability
Your decision to allow such a construct is a trade-off between guaranteed correctness and performance.
The builder pattern may give you a third way to handle this (depending if it is applicable to your construction of the list):
To construct the Container
create a Builder
which collects the list elements and then finally invokes the (private) Container constructor. This allows convenient collection of the list elements and avoids copying the list when constructing the final object:
public class Container { public static class Builder { public Builder add(String s) { strs.add(s); return this; } public Container create() { Container c = new Container(Collections.unmodifiableList(strs)); strs = null; return c; } private List strs = new ArrayList<>(); } private final List strs; private Container(List strs){ this.strs = strs; } }
Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72
0 comments:
Post a Comment