Immutable Class or Object
Many times during the interviews it is asked to create the immutable objects or class.
Now, I am just sharing my views on such questions, you can have different ones or better ones. Please share your views also, on this.
So when such question is asked then you can ask further questions to get the clear understanding of the requirements here.
And generally I see, people ask about immutability & expect the answers around immutable objects.
And such kind of arguments I had during interviews with HCL, Synechron, Globallogic, Morgan Stanley, Wissen & a few more. And every time these people think that immutability is just for objects only & such thing these people can see easily over internet. We have immutability at class & object level separate & one needs to be clear about this difference, else people have one common & fixed view that they need to make class as final, make its constructor as private, don't provide setters for the properties etc. But this common solution impacts your application.
If I have class 'A' & any method expects the objects of class 'A' type then one shouldn't be able to pass the objects of some custom class. As when one create a custom class extending class 'A' but has its custom definitions & such thing can cause security issues as one can cheat the method by providing objects of custom class and letting the method assume that this new working is in the actual class.
Architects or designers can name this anything to confuse the people further, but for me it is another place of mutation.
Let’s discuss above questions one by one –
public final class Mutable {
public String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Note the access modifier ‘final’ used here, this will prevent other classes to extend our class. So no one can override methods in our class. It is all to make the class immutable.
public class ImmutableSample {
public final String name;
public ImmutableSample(String name) {
this.name = name;
}
}
public class ImmutableSample {
private String name;
private boolean isName = false;
public String getName() {
return name;
}
public void setName(String name) {
if(!isName)
this.name = name;
isName = true;
}
}
Keep in mind, not to leave any variable open/public & for this way every access to property variables must be via getter/setter methods & must use the Boolean variables like shown above.
Suppose below ‘Mutable’ is the class & its objects we will be using in our class ‘Immutable’. Now user will pass the objects of ‘Mutable’ to our class or will be expecting such objects from our class.
public class Mutable {
public String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
But the objects of ‘Mutable’ returned by our class are mutable & user can change the properties of such objects even if we make our object as immutable. But we can create subclass of above class & will return objects of our subclass like shown below & all the properties are accessed via getter/setter methods–
public final class Immutable {
private Mutable mutable = null;
public void setMutable(Mutable mutable) {
if(this.mutable == null)
this.mutable = mutable;
}
public Mutable getMutable() {
SubMutable subMutable = new SubMutable(mutable.name);
return subMutable;
}
public static void main(String[] args) {
Immutable imm = new Immutable();
Mutable m1 = new Mutable();
m1.name = "m1";
imm.setMutable(m1);
Mutable m2 = new Mutable();
m2.name = "m2";
imm.setMutable(m2);
Mutable m3 = imm.getMutable();
m3.setName("m3");
m3.name = "m3";
System.out.println(m3.getName());
}
}
class SubMutable extends Mutable {
SubMutable(String name) {
this.name = name;
}
public final String name;
public String getName() {
return name;
}
}
Collections.unmodifiableList(list)
Collections.unmodifiableMap(map)
Collections.unmodifiableSet(set)
If your class is using the objects of some other class/es, then safe bet is to have the defensivecopies of such objects, i.e. first create the copy of the original object in your class & then return that copied object. So the reference of the original object will never leave the walls of your class, but you will create & return a copy of that original object every time. If you are being asked for immutability, then interviewer will be looking for word- Defensive Copies
So you can tell accordingly. But this answer is correct only when every time you are only one to provide these objects i.e. you are the only source & none will be passing your object further. As in this case you object data is safe with you, no matter if further systems are making changes its data. But if you are having chain of responsibility pattern or delegator pattern, then you will be passing your object to suppose, 'A' & then 'A' will do its work on the required data from your object & will pass it to 'B' and so on. So with defensive copy system, your object with you is safe but if 'A' makes any changes in the received object & then passes that changed object to 'B', you can't do anything there & here immutability behaviour breaks. So for such case you have to provide your custom class like shown earlier for 'SubMutable' class. It is very simple but in reality, you may have to override every method of the parent class to prevent any change in that object.
These ways, I believe, should work for maximum of your requirements.
But again, understand the flow of these objects in your application & expectation from those. It is not necessary you need 'Immutable' behavior everytime, which generally some 'Self Declared Intelligents' suggest to go for 'Immutable' obects.
Please let me know your views about the above ways. And again such immutability can be utilized effectively, if you are using 'final' keyword or not using ‘Reflection’.
Now, I am just sharing my views on such questions, you can have different ones or better ones. Please share your views also, on this.
So when such question is asked then you can ask further questions to get the clear understanding of the requirements here.
- Check if the person is asking to make the class immutable or the objects of a class immutable.
- If objects need to be immutable then is it required to make the further objects which are being used in your object to be immutable.
- What kind of other objects your object is using.
And generally I see, people ask about immutability & expect the answers around immutable objects.
And such kind of arguments I had during interviews with HCL, Synechron, Globallogic, Morgan Stanley, Wissen & a few more. And every time these people think that immutability is just for objects only & such thing these people can see easily over internet. We have immutability at class & object level separate & one needs to be clear about this difference, else people have one common & fixed view that they need to make class as final, make its constructor as private, don't provide setters for the properties etc. But this common solution impacts your application.
If I have class 'A' & any method expects the objects of class 'A' type then one shouldn't be able to pass the objects of some custom class. As when one create a custom class extending class 'A' but has its custom definitions & such thing can cause security issues as one can cheat the method by providing objects of custom class and letting the method assume that this new working is in the actual class.
Architects or designers can name this anything to confuse the people further, but for me it is another place of mutation.
Let’s discuss above questions one by one –
- Making a class immutable means that we want to prevent its definition to be changed further by any other class by extending/overriding our class.
public final class Mutable {
public String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Note the access modifier ‘final’ used here, this will prevent other classes to extend our class. So no one can override methods in our class. It is all to make the class immutable.
- Now other scenario – Now interviewer asks to make its objects as immutable too. Now just you can ask about the number & kind of variables it will be holding. Because accordingly we have to decide
the way to introduce the immutability. - Simple case – class is just like above class having one variable that too either primitive type or String, then it is simple like shown below but it will be fine when there are only few such variables which need to be set & even if number of such variables increases then we have to look for case(b) –
- When no get() is required & variables can be made public then make that variables as final & take their values via constructors like shown below –
public class ImmutableSample {
public final String name;
public ImmutableSample(String name) {
this.name = name;
}
}
- If variables need to be made private & their values can only be accessed via some getter methods then make the variables as private & provide the getter methods for those variables.
- If there are many variables, then it will be difficult to get all the values via constructor. For this we need to provide both getter & setter methods, then we have to add equal number of Boolean type variables to our class & each property variable will be having mapping Boolean variable like shown below –
public class ImmutableSample {
private String name;
private boolean isName = false;
public String getName() {
return name;
}
public void setName(String name) {
if(!isName)
this.name = name;
isName = true;
}
}
Keep in mind, not to leave any variable open/public & for this way every access to property variables must be via getter/setter methods & must use the Boolean variables like shown above.
- Now another tricky scenario. Suppose your class object is using the objects of other classes. So like ways shown above you can make your object state immutable but how can you make objects of other classes immutable when you return those objects either through getter methods or you have made instance variables as public. So in such case you can make sure that your instance variables will not point to other objects, but users can modify the properties of such objects after your object returns those objects to users. So how can you make such objects immutable?
Suppose below ‘Mutable’ is the class & its objects we will be using in our class ‘Immutable’. Now user will pass the objects of ‘Mutable’ to our class or will be expecting such objects from our class.
public class Mutable {
public String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
But the objects of ‘Mutable’ returned by our class are mutable & user can change the properties of such objects even if we make our object as immutable. But we can create subclass of above class & will return objects of our subclass like shown below & all the properties are accessed via getter/setter methods–
public final class Immutable {
private Mutable mutable = null;
public void setMutable(Mutable mutable) {
if(this.mutable == null)
this.mutable = mutable;
}
public Mutable getMutable() {
SubMutable subMutable = new SubMutable(mutable.name);
return subMutable;
}
public static void main(String[] args) {
Immutable imm = new Immutable();
Mutable m1 = new Mutable();
m1.name = "m1";
imm.setMutable(m1);
Mutable m2 = new Mutable();
m2.name = "m2";
imm.setMutable(m2);
Mutable m3 = imm.getMutable();
m3.setName("m3");
m3.name = "m3";
System.out.println(m3.getName());
}
}
class SubMutable extends Mutable {
SubMutable(String name) {
this.name = name;
}
public final String name;
public String getName() {
return name;
}
}
- Now suppose if your class is using the objects of Collection type & you don’t want user to make any changes in the collection objects returned by your class.
Collections.unmodifiableList(list)
Collections.unmodifiableMap(map)
Collections.unmodifiableSet(set)
If your class is using the objects of some other class/es, then safe bet is to have the defensivecopies of such objects, i.e. first create the copy of the original object in your class & then return that copied object. So the reference of the original object will never leave the walls of your class, but you will create & return a copy of that original object every time. If you are being asked for immutability, then interviewer will be looking for word- Defensive Copies
So you can tell accordingly. But this answer is correct only when every time you are only one to provide these objects i.e. you are the only source & none will be passing your object further. As in this case you object data is safe with you, no matter if further systems are making changes its data. But if you are having chain of responsibility pattern or delegator pattern, then you will be passing your object to suppose, 'A' & then 'A' will do its work on the required data from your object & will pass it to 'B' and so on. So with defensive copy system, your object with you is safe but if 'A' makes any changes in the received object & then passes that changed object to 'B', you can't do anything there & here immutability behaviour breaks. So for such case you have to provide your custom class like shown earlier for 'SubMutable' class. It is very simple but in reality, you may have to override every method of the parent class to prevent any change in that object.
These ways, I believe, should work for maximum of your requirements.
But again, understand the flow of these objects in your application & expectation from those. It is not necessary you need 'Immutable' behavior everytime, which generally some 'Self Declared Intelligents' suggest to go for 'Immutable' obects.
Please let me know your views about the above ways. And again such immutability can be utilized effectively, if you are using 'final' keyword or not using ‘Reflection’.