I am looking for some efficient way for building a immutable class, just like Java's String class.
All the fields must be
private and preferably final
Ensure the class cannot be
overridden - make the class final,
or use static factories and keep
constructors private
Fields must be populated from the
Constructor/Factory
Don't provide any setters for the
fields
Watch out for collections. Use
Collections.unmodifiable*. Also, collections should contain only immutable Objects
All the getters must provide
immutable objects or use defensive copying
Don't provide any methods that
change the internal state of the
Object.
Tom Hawtin pointed out that final can be optional. String class has a cache hash var that is only assigned when the hash function is called.
If you populate all fields using the constructor and make the fields final - you are partway there.
If the fields use custom types - you may need to make them immutable as well.
Any fields that are collections should use the unmodifiable collections - to be on the safe side.
You need to worry about the object graph!
Any methods on the object need to take care with non-final fields. E.g. String.add creates a new String. If you need to mutate one field - do so via a copy constructor.
Finally make the object final.
An object is immutable if none of its fields can be modified, so those fields must be final. If you don't want your object to be subclassed, you can make the class itself final as well, just like String is.
To easily construct an immutable object with a lot of information, you should look at the Factory Pattern
For more information, see Wikipedia
Related
I would like to have some guarantee that instances of some particular class Content is only accessed by its "owner", and if another object wants the same Content it needs to take a deep copy. Coming from C++ I would achieve that using a unique_ptr, is there anything similar in Java?
Currently I am resolving this by just keeping the Content private everywhere I keep one and paying attention to creating a new Content (the constructor implements the deep copy mechanism) on a getContent. But I have no means of enforcing possible other users of the Content class to follow the same pattern, it's easy to forget. It would be nicer if it could take care of itself somehow, like not being copyable.
I realize that it goes somewhat against the spirit of the language, but in some cases I think it's justified. For example, if Content represents some stream of data that is modified even by reading it. I thought, if not in the core language, maybe there is some #interface for compile-time checking or a way of creating one?
Edit: The idea is that the owner can modify the object freely, before or after taking copies, and if someone takes a deep copy, they can modify theirs (not affecting the original), so making the Content immutable is a bit too harsh (unless I'm misunderstanding what that implies).
There are a couple of common strategies here:
Privacy with defensive copying
In this strategy, you'd have the owner have a private reference to the content, and if it's appropriate for it to give out copies of that content, to do so via a defensive copy:
class Owner {
private Content content;
// ...unnecessary detail omitted...
public Content getContent() {
return new Content(this.content);
}
}
The Cloneable interface can sometimes be useful here.
Immutable objects
The other common strategy is to use immutable objects (e.g., ensure that Content, once instantiated, cannot be modified). Then you don't care who has a reference to the content, since they cannot change it.
No there isn't.
Once you have established a reference to an object, there's absolutely nothing you can do to stop someone form assigning another reference to that object via that established reference.
Java programmers get round this by making objects immutable (see java.lang.String). Then you ought not give two hoots about who else is referring to a particular instance.
You can declare the class Content as Immutable by doing this:
Don't provide "setter" methods — methods that modify fields or objects referred to by fields.
Make all fields final and private.
Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final.
If the instance fields include references to mutable objects, don't allow those objects to be changed
Here is a java official doc: https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html
Java does not have something like that. There are some language elements that can help with such requirements:
Enums that have only one constant; to be used as "built-in" singletons
Methods in Collections to create immutable copies of collections
And of course, you can make all fields in your class final; so they get initialized only during construction time; to prevent later changes
But as Java is also missing a const concept, you can partially work around such things. Like in:
class Foo {
private final List<Bar> bars = new ArrayList<>();
doesn't mean that instances of Foo will be immutable - as you still can add/remove elements to that list owned by Foo.
Similar; given
List<Foo> root = ...
List<Foo> immutableCopy = Collections.unmodifiableList(root);
one can still change that immutableCopy ... by messing up root.
In one of the interview I was asked 'How String is made immutable?'
As i wasnot sure about the answer, i didnot reply. I asked the interviewer later regarding the same. Answer was String class is final that's how immutability is achieved.
Is that the correct answer? if yes, even StringBuffer is also marked as final class. Then why not StringBuffer is immutable?
It is a combination of:
Fields are private - so you cannot change them directly.
No set methods provided - so they cannot be changed indirectly either.
String is final - so you cannot add mutability (i.e. setters etc.) to it.
No that's not the correct answer. String achieves immutability because it doesn't provide you any method to change its internal contents. Thus you can instantiate a String object, assign a reference to it but cannot change its contents once initialized.
String is immutable object.
Make a class immutable by following these guidelines :
ensure the class cannot be overridden
make the class final, or use static factories and keep constructors private
make fields private and final
do not provide any methods which can change the state of the object in any way - not just setXXX methods, but any method which can change state
if the class has any mutable object fields, then they must be defensively copied when passed between the class and its caller
force callers to construct an object completely in a single step, instead of using a no- argument constructor combined with subsequent calls to setXXX methods (that is, avoid the Java Beans convention)
The final keyword is not the same as immutability. String is immutable as it does not define any methods that allow a user to change its content and it is final, removing the possibility to change things in a subclass.
Making something like a List instance variable final will still allow you to change its contents, making it mutable.
Being final means it can't be derived from. That doesn't confer immutability
Immutability is achieved by encapsulation and not providing any means to amend the internally held character array. I.e. no methods exist to modify the internal fields.
A pool of strings, initially empty, is maintained privately by the class String.
You should look at the JavaDoc of String:
public native String intern();
See:
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#intern%28%29
http://en.wikipedia.org/wiki/String_interning
The usual way to make a class immutable is to ensure that:
all the fields are private;
there is no way to modify the fields after construction;
it is final (so that extensions cannot break immutability).
String is a bit special, at least in the Sun/Oracle implementation in that it does not actually follow this procedure. The implementation has a mutable field in which it caches the hash code of the object. So while there is a method that changes the internal state of the object (hashCode), this state change does not change the behaviour of the object in any way. Any subsequent calls to hashCode will run faster, but the result won't be any different.
I wonder, In Java How can we create a constant object (but not-reference nor immutable since immutability is a feature to all objects of a class) ?
First:
final MyClass c = new MyClass();
creates a constant reference to non-constant object hence I can do:
c.setData(100);
Second:
String class is a class that all its instances should be constant (a.k.a immutable object). I need to have a kind that I can create from a constant objects and non-constanct objects.
In Other words, How to grant the constant-ness to some objects of a class and remove it from other objects. (without the need to wrap this object inside any wrapper).
I suppose that you want something along the lines of the const keyword in C++, which makes an instance of an otherwise mutable class immutable. However, no direct equivalent for this exists in Java.
If you control the class, you could define an interface that only exposes the getters and use that interface whenever you need a "const" reference - this would not require any wrapping, but it would be rather cumbersome if you need to do this for a lot of classes.
The closest you could do is to extend the base class and override its setter methods so they throw java.lang.UnsupportedOperationException , that way you can create object from the base class or the immutable subclass...
And what about an Enumeration containing only one element ? I think that comes pretty close to what he needs
In C++ a getter & setter for a private data member is very useful due to the ability to control mutability via a const return value.
In Java, if I understand correctly (please correct me if I am mistaken), specifying final on a getter doesn't work that way. Once the caller received the data member reference through the getter, it can modify it, despite it being private...
If that's the case (and please correct me if I have a gross misconception here), why not declare the data member public and simplify things?
Making immutable return values in java is a matter of either returning already immutable objects types (such as String) or returning a copy for non-immutable objects.
Sample 1 - Already immutable object
public String getValue() {
return value;
}
Sample 2 - Collection of already immutable objects
public List<String> getValues() {
return new ArrayList<String>(values);
}
Sample 3 - Non-immutable object
public Complex getComplex() {
return complex.clone();
}
Sample 4 - Collection of non-immutable objects
public List<Complex> getComplex() {
List<Complex> copy = new ArrayList<Complex>(complexs.size());
for (Complex c : complexs)
copy.add(c.clone());
return copy;
}
Sample 3 and 4 are for conveniance based on that the complex type implements the Cloneable interface.
Furthermore, to avoid subclasses overriding your immutable methods you can declare them final. As a side note, the builder pattern is typically useful for constructing immutable objects.
If you want your class to be immutable (i.e. having only final fields and getters) you must be sure that the values you return are immutable as well. You get this for free when returning Strings and built-in primitives, however some extra steps are necessary for other data types:
wrap collections with immutable decorators or defensively copy them before returning from a getter
make a copy of Date and Calendar
Only return immutable objects or defensively clone them. This also applies to objects in collections.
Note that if you defensively copy a collection, the client can view or modify the copy, but this does not affect the original collection:
return new ArrayList<Foo>(foos);
On the other hand if you wrap the original collection, the client is able to see all the changes that were introduced to the collection after the wrapper was created, but trying to change the contents of the wrapper will result in runtime exception:
return Collections.unmodifiableList(foos);
The bottom line is: Foo has to be immutable as well, otherwise the collection is immutable, but the client code can still modify members of the collection. So the same rules apply to Foo.
If that's the case (and please correct me if I have a gross misconception here), why not declare the data member public and simplify things?
Because:
you might wish to store mutable data inside an object and only provide immutable (read-only) view of the data (like wrapping collections)
you can change the implementation in the future, get rid of the field and for instance compute the value on the fly.
If you want to return an immutable view of a mutable standard container (eg list), then you should take a look at the Collections library:
http://download.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html
It provides some useful wrappers such as unmodifiableMap and unmodifiableList. That way you don't have to make a wasteful copy. Of course, if the elements of the list are mutable, then this won't help as much -- there's no easy way in Java to get "deep" immutability. Of course, the same is true in C++ -- e.g., if you have a const vector of pointers to Foo objects, then the Foo objects themselves can still be modified (because const doesn't propagate across pointers).
If that's the case (and please correct me if I have a gross misconception here), why not declare the data member public and simplify things?
First of all, the JavaBeans spec. requires you to provide getters (and setters for mutable properties).
Second, getters might enable you to add some logic, e.g. one getter might actually decide what to return (e.g. if the property is null return something differenc). If you didn't have getters in the first place you'd have more trouble to add such logic later on. With getters you'd just change the method without touching the callers.
why not declare the data member public and simplify things?
Because information hiding makes it easier to manage and maintain a complex codebase. If the data members are private, you can change representation and behavior in one class, rather than throughout a large codebase.
Once the caller received the data member reference through the getter, it can modify it, despite it being private...
To clarify, a caller cannot modify a data member returned from a getter. It might be able to modify an object to which the data member points.
If this is a problem, and you're providing access through a getter, you can return an immutable instance, or a defensive copy.
The setter is also valuable for controlling modification to a referenced object. You can make a defensive copy in the setter.
I need to persist several classes with A LOT of static fields (which are arrays filled & modified during the runtime). It would take a lot of effort to convert from static fields to instance vars, so I'd rather go for a quick solution, if any.
So far the path of least resistance is to cook my own writeObject() for each class.
Alternatively, i dont need Serialization as such - any mechanism to store/load an object from persistent storage will do. E.g. XMLDecoder to decompose the bean objects, etc.
You could write a method to use reflection to serialize all static methods. A static method can be marked transient which would normally be redundant, but you could use this to highlight static fields you don't want to serialize. You can call this method from your writeObject() to save you having to do this for every field.
I'd create a new class that gathers all those static fields, lets call it StaticInfoClass. In StaticInfoClass create all the fields non-static. Create a property in the old class that is type of StaticInfoClass. All instances of the your original class will hold a reference to a unique instance of StaticInfoClass, that will contain all the arrays filled and modified during the runtime. If you have threads make sure you make it a bean with synchronized methods to avoid race conditions.
With this approach, in essence, you are implementing static fields without actually using the static modifier. This simple approach should easy a lot your serialization and deserialization problems and most frameworks will handle it very easily.
Also remember that static fields and global state in programs are normally a bad practice, it should be avoided. I tend to not use static if it is not to declare constants or other trivial data structures that definitely do not changed in runtime.
Have not tried this but might work. if your class defines an array of ObjectStreamField objects named serialPersistentFields , then you can explicitly declare the specific fields saved. You can shove any value into it, even the static fields.
private static String lastUser;
private static int maxAge;
private final static ObjectStreamField[]
serialPersistentFields = {
new ObjectStreamField(
"lastUser", String.class),
new ObjectStreamField("maxAge", int.class)
};
Then you will have to implement readObject, to fetch these values and set it for your static variables. So basically this mechanism allows you to marshall/unmarshall fields from anywhere via serialization. You just need to know what to do with them once you read them back. I would still recommend paying the price for moving your statics to member variables.
details : http://java.sun.com/developer/technicalArticles/ALT/serialization/