I am reading about the specific guidelines that needs to be followed while creating Immutable Class in Effective Java.
I read that In Immutable class method should not allowed to be overridden otherwise overridden method may change the behaviour of method. Following are the design approaches available in java to solve this problem :-
We can mark class final but as per my understanding, it has a one disadvantage that it makes the class inextensible.
Secondly is to make individual methods final but I can not get other disadvantage besides that we need to individually mark each method as final in order to prevent overridding.
As per book,better approach is to make the constructor private or package-private and provide public static factory method for creating object.
My question is: Even if we include private or default constructor in the class, it cannot be extended anymore in same package (in other package in case of package-private constructor), it has a same problem which the first one had. How is it considered as the better approach than the previous ones?
An immutable object should not be extensible. Why?
Because extending it will allow either direct access to fields (if they are protected which would allow writing methods that change them), or adding state which may be mutable.
Imagine we wrote a class FlexiblyRoundableDouble that extends Double, which has an additional field roundingMode that lets us choose a "rounding mode". You could write a setter for this field, and now your object is mutable.
You can argue that if all the methods are set as final, you cannot change the original behavior of the object. The only methods that could access your roundingMode field are new methods that are not polymorphically available if you assign your object to a Double variable. But when a class's contract says that it's immutable, you make decisions based on that. For example, if you write a clone() method or copy constructor for a class that has Double fields, you know that you don't need to deep-copy the Double fields, as they do not change their state, and can therefore be safely shared between the two clones.
Also, you can write methods that return the internal object without fearing that the caller will then change that object. If the object was mutable, you'd have to make a "defensive copy" of it. But if it's immutable, it's safe to return a reference to the actual internal object.
However, what happens if someone assigned a FlexiblyRoundableDouble to one of your Double fields? That object would be mutable. The clone() would assume it isn't, it will be shared between two objects, perhaps even returned by a method. The caller would then be able to cast it back as a FlexiblyRoundableDouble, change the field... and it will affect other objects that use that same instance.
Therefore, immutable objects should be final.
All this has nothing to do with the constructor issue. Objects can be safely immutable with public constructors (as demonstrated by String, Double, Integer and other standard Java immutables). The static factory method is simply a way utilizing the fact that the object is immutable, and several other objects can hold references to it safely, to create fewer objects with the same value.
Providing a static factory method gives you room to implement the Flyweight Pattern.
They're stating that you should hide the possibility of creating a new object using a constructor, and should rather make a call to a method which checks if an object with similar state exists in the "object pool" (a map filled with objects waiting to be re-used). Not re-using immutable objects is a waste of memory; this is why String literals are encouraged, and new String() is shunned (unless needed).
class ImmutableType {
private static final Map<Definition, ImmutableType> POOL = new HashMap<>();
private final Definition definition;
private ImmutableType(Definition def) {
definition = def;
}
public static ImmutableType get(Definition def) {
if(POOL.contains(def))
return POOL.get(def);
else {
ImmutableType obj = new ImmutableType(def);
POOL.put(def, obj);
return obj;
}
}
}
Definition stores the state of the ImmutableType. If a type with the same definition already exists in the pool, then re-use it. Otherwise, create it, add it to the pool then return it as the value.
As for the statement about marking the class final, immutable types should not be extensible in the first place (to avoid possibly modifying behavior). Marking every method final is just crazy for immutable classes.
Related
I have been trying to grasp concept of multi-threading and confused about the below code:
class MyClass{
private StringBuilder content = new StringBuilder();
public void setContent(){
content.append("Some String");
content.append("more String");
}
public String getContent(){
return content.toString();
}
}
My understanding is that MyClass cannot be made thread safe just by synchronizing its setter and getter methods. Because while creating MyClass object ,content reference may have improper object initialization. To make proper initialization the content should be final.
Can anyone help me to clarify it?
My understanding is that MyClass cannot be made thread safe just by synchronizing its setter and getter methods.
That is not correct.
Provided that the reference for a MyClass instance is safely published to all threads that use it, then synchronized getters and setters will see the correct initial state for the object.
If you declare content (and any other fields) to be final you can dispense with the requirement for safe publication. However, since this is not an immutable class, it will still be necessary for the getter and setter to synchronize.
The special semantics for final fields (as described in JLS 17.5) allow truly immutable objects to be thread-safe without any synchronization overheads. But these semantics are not directly applicable in your example because the "setter" is mutating the object.
Incidentally, if content had type StringBuffer rather than StringBuilder AND the variable was final. The result would be "mostly" thread-safe without synchronized. That is because StringBuilder is thread safe for these operations. The only catch is that your "setter" is calling append twice. Without a synchronized, it would be possible for a getter to see the intermediate state of the buffer.
Immutability is not always the answer to thread-safety. Lets first examine the potential thread-safety issues in the existing code. The potential problem is when you have two threads (A, and B) accessing the setter method setContent() simultaneously. That would result in having a randomized output String that might look like Some String Some String more String Some String Some String because you have no way to ensure that more String must be added right after Some String.
That logic could be perfectly fine in your application. However, if you still need to ensure that those two append statements are added together, that is when synchronization come in place. In that case, you could synchronize the setter method to ensure that only one thread at a time can access it.
Do not worry about having null StringBuilder because your method will not be accessed without instantiating the MyClassinstance first.
Hope this helps
Immutability and Thread-Safety goes hand in hand , if you are able to make your class Immutable then its said the class will be inherently thread safe , however to achieve same is not easy.
To create immutable class in java, you have to do following steps.
Declare the class as final so it can’t be extended.
Make all fields private so that direct access is not allowed.
Don’t provide setter methods for variables
Make all mutable fields final so that it’s value can be assigned
only once.
Initialize all the fields via a constructor performing deep copy.
Perform cloning of objects in the getter methods to return a copy
rather than returning the actual object reference.
but do read this https://dzone.com/articles/do-immutability-really-means as this gives a food for thought on immutable classes
Most of us understand the consequences of shared mutability, and it is said that always prefer immutability(final modifier, set once and you can't change it) if you have a chance. I have seen few coding examples where People are actually making fields final or setters as private or even removing setters for a class (which can be DTO, Model or Entity class) and another class (a builder class which can set values once to that immutable class) is used to create and set fields of the Immutable class To ensure no other class is able to modify the state. Which seems a burden to me. SO I have come-up with this thought (below I am giving an example)
public class TestDataClass {
private String name;
public String getName() {
return name;
}
public void setName(Supplier<String> supplier) throws Exception {
if(Objects.isNull(name))
{this.name = supplier.get();return;}
throw new Exception("This field is immutable and already has a value "+this.name);
}
}
In this way either you can set values through setter like this objectOfTestDataClass.setName(() -> {return Perform_Desired_Logic;});
or
objectOfTestDataClass.setName(() ->"My Name"); if it is plain setter. Then also you dont have to create a bulder class or make setters private or omit setter method
In this way, I can get rid of variable initialization during Instantiation also once you set fields to become Immutable(I am not considering reflection).
I want your expert opinion to validate how legitimate is my thought, Can I consider this as Immutability? Am I missing something? in that case please correct me.
There are several things to note
Using a Supplier<String> instead of a String does not improve the code. There are only two cases, the intended case where the method is only executed once and the code of the supplier gets executed immediately and the erroneous case, where the supplier does not get executed, but where’s the sense in optimizing the erroneous case?
If a particular property supports being null, that approach fails to handle the case when it should be fixed to `null.
The API signature does not indicate that the class should be treated like immutable. Most readers will assume that it is mutable. So they may try to modify the object and not even notice the error if you’re going to remove the exception throwing statement, as said in a comment.
Immutable objects created by a builder are definitely completed and truly immutable once build. In contrast, your class allows the creator to forget setting some properties to fixed values, producing an actually mutable object.
Since instances of this class are not guaranteed to be immutable, they also do not have the guaranty to be thread safe that is usually associated with immutable objects.
What you wrote allows to not set more than one time a field of an object.
But it is not a way to create object with a fully initialized state as a constructor or a builder can provide.
So, if the client manipulates the object with a not complete or corrupted state, it could not work as expected.
Besides, providing setters that may be invoked by the clients at compile time but which the misuses would be known only at runtime (by throwing an exception) is not a friendly and good designed API.
Example of issue with an object that has a not complete state.
Take a Rectangle class.
It is composed of 4 mandatory information (height, weight, x and y coordinates).
These are represented by 4 instance fields :
int x, int y, int width, int height
Suppose the class provides an instance method boolean contains(Point p) to determinate if a Point (x, y coordinates) is included in it.
If you apply your method to value fields of this class, you may create Rectangle instances with incomplete/partial state.
The contains() method could not work. It should perform different checks and if a field is missing in Rectangle, it should may be even throw an exception.
Example of issue with an object which the state may be corrupted
If your object may be manipulated by multiple threads, using your way to value the fields of the object may set the object in an unexpected and inconsistent state.
Two threads may manipulate the object at the same time and changing two fields that should not be changed in this way.
To avoid it, you are forced to use explicit synchronization mechanisms for both reading and writing of fields.
Ii you use a constructor or a builder, you have not these problems as you get out of the box a complete, unmodifiable (de facto thread-safe) object with a clear API.
Good morning, i'm learning java and i have a question.
I have a class "table" with a constructor, that accept a "fields", and put it in PRIVATE variable.
the question is: it is right to pass the object and use a "=" to put in the PRIVATE variable, or it's better to clone it?
if i use a "=", the variable inside my class are still editable from the method that used the constructor of the class, and eventually put NULL inside it.
for example:
class Table{
private Field field;
table (Field field)
{this.field=field;}
public String getValue()
{return field.toString(); }
}
main{
Field field=new Field("VALUE1");
Table table(field);
field.value="VALUE2";
System.out.println(table.field.getValue());
}
and the result is "VALUE2".
So in the table passed a value, and then i alter it.
but for the "good programming art", it is acceptable, or is better
class Table{
private Field field;
table (Field field)
{this.field=field.clone();}
public String getValue()
{return field.toString();}
}
main{
Field field=new Field("VALUE1");
Table table(field);
field.value="VALUE2";
System.out.println(table.field.getValue());
}
prints VALUE1
so if i pass a value to a Table, i can't modify it without using the Table methods?
what is the right way to to this?
This is a good question and points to a real problem. The recommended way to do this would be to have your classes immutable.
So the problem is not in the Table class, but in the Field class - it should only allow the modification of the value through the constructor, not through direct changes or with setters. Doing that you won't have this issue.
Declaring a variable private has nothing to do with its immutability. If the object passed to you is not immutable then I would suggest making a (deep) copy, otherwise you cannot rely on it not being changed elsewhere.
Other way would be making the Field class immutable, then you wouldn't have to make a copy, you would just save the reference in a private field.
There is no right or wrong way to do this in Java. Java passes objects by reference, and you need to understand that objects passed by reference are usually mutable, meaning they can change state. In Java, this is the expected behavior, but it can be confusing at first. It can also be very difficult to manage in a multi-threaded environment.
You do have the option, as #eis has indicated, to use immutable objects. There are many advantages to this, especially in multi-threaded code, but also some disadvantages. That discussion is too long and involved to get into here.
If you are concerned specifically with Java collections, the collections framework allows you to make a collection immutable. See the java.util.Collections.unmodifiable* methods for details on how to do that. Those methods can make an unmodifiable view of a collection without the overhead of cloning the data.
When you want the second object to see your original object over its lifetime, no matter how you change it, clone it before you pass it, or use an immutable object in the first place. When you want to ensure the second object cannot change your object, make it either immutable or use a read-only view as the Java collections do.
Good morning to you too.
I guess that you already know that Java is pass by reference value, so in the first case, table.field and field are "pointers" to the same object. Thus, modifying one will modify the other and viceversa. If that is what you want in this case then your first implementation would be correct.
On the other hand, if you just want to pass an object and you wouldn't be using the object field that you created, the following would be better suited:
Table table(new Field("Value 1"));
Lastly, if you just want to pass the value and you field and table.field referencing different objects that happen to have the same value. Modifying one won't modify the other. The clone() method is a valid solution, but not all classes implement this method. If the class Field didn't support the method clone(), your best bet is to implement a method similar to this in the Field class:
class Field {
//...Your code...
//First possibility
public void copyField(Field originalField) {
this.atribute1 = originalField.attribute1;
this.atribute2 = originalField.attribute2;
//This way you copy all the attributes manually
}
//Second possibility (a static method)
public static void copyField(Field newField, Field originalField) {
newField.atribute1 = originalField.attribute1;
newField.atribute2 = originalField.attribute2;
//This way you copy all the attributes manually
}
}
//**Using each method to make a copy of field1 in field2**
Field field1 = new Field(...);
Field field2 = new Field();
field2.copyField(field1); //Non-static method
Field.copyField(field1, field2); //Static method
Yet another solution would be to make a copy constructor which would be almost exactly the same as the non-static method:
public Field(Field fieldToCopy) {
this.atribute1 = fieldToCopy.attribute1;
this.atribute2 = fieldToCopy.attribute2;
//...
}
As you can see there are several correct ways to do this. You need to be able to chose and implement any of them depending on the particular problem you are solving.
Strategy for defining immutable class says that
all the fields should be final.
For ex:
private String name;
Why does it have to be final?
Since I am not giving setter methods for it? It can't be changed.
Thanks.
If you read
private final String name;
you know the field is immutable.
If you read
private String name;
you have to read the entire class to check it is not changed anywhere. This is means much more work for you.
You may remember now, having just written the class that you didn't add a setter, but after writing many more classes you read your own class six month later, you won't remember reliably.
Even if it is not changed now, someone (possibly yourself) could change it later by adding code. However, you might have made the assumption the value won't change.
In short, only make it non-final when you mean the value to change, and make it final when you didn't expect it to change. Don't leave it as a may be/may be not.
Now imagine you are used to being clear about which fields can be changed and which cannot. This saves you a lot of work when reading some else's code. But you discover that you are reading code which is not clear and non-final doesn't mean it was changed, it now means you have to check things, you wouldn't normally have to check which is one more headache in trying to understand some code you really don't need.
A simple example of how much harder it is to read code to determine if a field is effectively final.
public class A {
static class B {
private int x;
}
// some code
This all looks fine up to this point, no setters or even methods in B. So B.x is immutable right?
static class C {
public void update(B b, int x) {
b.x = x; // this really compiles
}
}
}
Oops no, you have to read the whole class file.
It is far better for you to make every field you can final (which should have been the default IMHO) when you write the code, rather than leaving it for someone to figure out later.
The main reason (IMHO) is that when field is final is guaranteed to be visible in other threads immediately after constructor is finished.
Keeping the field final emphasizes the fact that it cannot be changed anywhere else.
Self documenting code the the field should not be changed
Compiler will help you by giving error if you change the field somewhere else
So final helps in many ways for making object Immutable.
It's good practice to make immutable fields final, even on otherwise mutable objects.
Note that private fields of one object in fact CAN be accessed by other instances of the same class.
An object (class or instance) is immutable, if its internal state cannot be changed (reflection doesn't count).
Making a field final guarantees only that the value (if it's a primitive) or reference (for non-primitives) cannot be changed.
For non-primitives, this doesn't automatically mean that the referenced value is also immutable. Which means that if your final field references, for example, a list, one cannot exchange the list, but add/remove values from it, thus changing the state of the object.
For an object to be immutable:
The internal state must be determined upon construction and can never change
This means all fields that define the state must be final (you may have other helper fields which don't belong to the state, that's ok but rare).
This also means that all refernced objects must be immutable. Some objects such as String are already immutable, others such as collections can be wrapped to make them immutable (Collections.immutableList|Set|Collection|...)
Making primitive types final ensures immutability. However making non primitive objects final sometimes makes no sense since final object states can be mutated.As Greg points out this depends on the type of Object in question
As the example you showed, all properties are primitive hence final keword make sense.
One benifit of declaring a field final is that it allows compiler to detect attempts to change the field during refactoring. A class can be immutable even if its fields are not final.
JVM guarantees that final fields of a class will be initialized before any thread gets hold of the object. Without this guarantee, a reference to an object may be published, i.e. become visible, to another thread before all the fields of this object are initialized, due to reorderings or other optimizations. This could cause racy access to these fields.
This is why, when creating an immutable object, you should always make all its fields final, even if they are not accessible via getter methods.
To make a class immutable what I can do is:
1)Make class final
2)do not provide setters
3)mark all variables as final
But if my class has another object of some other class then , somone can change value of that object
class MyClass{
final int a;
final OtherClass other
MyClass(int a ,OtherClass other){
this.a = a;
this.other = other;
}
int getA(){
return a;
}
OtherClass getOther(){
return other;
}
public static void main(String ags[]){
MyClass m = new Myclass(1,new OtherClass);
Other o = m.getOther();
o.setSomething(xyz) ; //This is the problem ,How to prevent this?
}
}
A) Make the OtherClass immutable as well
or
B) Don't allow direct access to the OtherClass object, instead providing only getters to act as a proxy.
Edit to add: You could make a deep copy of OtherClass and return a copy rather than the original, but that generally isn't the type of behavior you would expect in Java.
Immutability is best considered from the perspective of the API user. So your object API needs to satisfy the following two conditions:
No way for an external user to change the value of the object
A guarantee that any time the user reads or makes use of the object's value in the future, it will get the same result
Important note: It is in fact OK to have mutable data inside an immutable object as long as it behaves as an immutable object from the perspective of the API user. Consider java.lang.String for example: although it is generally considered as the definitive immutable class, it does in fact have a mutable internal field for caching the hashCode (not many people know this!).
So to address your question, if you wish to contain another (mutable) object inside an immutable object then you typically need to do one or more of the following:
Guarantee that nobody else can change the value of the mutable object. Typically this means ensuring that no-one else can have a reference to the mutable object, so this is only usually possible if you create the object yourself rather than accept a reference from outside.
Take a defensive deep copy of the mutable object, and don't hand out references to the new copy. Only allow operations that read the new copy in the public API. If you need to hand out a reference to this object, then you need to take another defensive copy (to avoid handing out a reference to the internal copy).
Use an immutable wrapper for the mutable object. Something like Collections.unmodifiableList. This is useful if you want to hand out a reference to the internal mutable object but don't want to run the risk of it being modified.
All of these solutions are a bit hacky - a better solution overall is to avoid the use of mutable objects within immutable objects. In the long run it's asking for trouble because sooner or later a mutable reference will leak out and you will have an extremely hard to find bug. You are better moving towards a full hierarchy of immutable objects (the approach taken by languages like Scala and Clojure)
I assume OtherClass (by the way you say Other once) is meant to be a class you don't control, or which has to have a setter.
If you can't remove getOther, change it to getOtherView and return a read-only view of other. There will be wrappers for all the get methods, but no set ones.
Return deep clones from your getters. You may find this to be no easy task.
All the objects referenced in the immutable class should be immutable, or at least be encapsulated as private and making sure that they are not modified (not inside the methods of your class and definitely not from the outside). For instance, if you have this situation:
public class MyImmutable {
private MutableClass mutableObject;
}
... You can not provide the getMutableObject() method, because doing so will open the door for outside modifications, like this:
myImmutable.getMutableObject().setSomeAttribute(newValue);
As a special case of the above, all collections and/or maps should be made immutable, with the ummodifiableXXX() methods in the Collections class.
you cannot (reasonably) stop that in java. if you don't have control over the other class, there are ways to effectively get immutable behavior, but it can be very expensive in practice. basically, you must always return a copy of that class in any public method return values. (the jdk actually has this problem with the TimeZone class).
But If my class has another object of some other class then , somone
can change value of that object...
Java objects are not primitive. If you mark a primitive as final, then its value cannot be changed once it is assigned. However, object contents cannot be final, only object references can be final. So you cannot make an object in this way.
One solution might be abandoning all setter/mutator methods those could change the particular fields of the object and encapsulating them in a way that you can only access them, not change them.
It is possible to create the immutable class in java by following ways
1.Don't Provide setter methods.
2.Make all fields are as final and private.
3.Make Class as final.