Immutable class in Java - java

As per many documentations, I have seen that an immutable class should have the following features:
class should be final
all the methods should be final
all the variables should be final
there should not be any setters
But my questions are:
What if I have a class with only final variables?
If I do have setters also, I cannot change the state of the Object as I have all the final variables. So how will this affect immutability?
How can inheritance change the object state in this case?

1.What if I have a class with only final variables?
That will get you far but not all the way. The types of those variables also need to be immutable. Consider for instance
class MyImmutableClass {
// final variable, referring to a mutable type
final String[] arr = { "hello" };
// ...
}
This allows someone to do
myImmutableObject.arr[0] = "world";
and effectively mutate objects of your immutable class.
Also, it's recommended prohibit extending the class (because there's no way to force subclasses to be immutable). See answer to your third question below.
If I do have setters also, I cannot change the state of the Object, As i have all the final variables. so how will this affect immutability.
That's right. If all variables are final, standard setter methods can't exist.
how can inheritance change the object state in this case?
A subclass can't change the state of final fields of the super class. But there's another issue with inheritance.
If you have an immutable Animal subclassed by a Dog, and the Dog has a setDogsName method that mutates the object, then in effect you may have Animal objects (of type Dog) that are in fact mutable.
In other words most (all?) benefits of immutability is lost if an immutable class is open for extension: If you receive an Animal as a parameter to a method for instance, you can't assume it's immutable. You can't safely put Animal objects as keys in hash maps, etc.
Basically the original statements are a bit redundant, which is why I think they are a bit confusing:
A final class can't be extended, so it's redundant to also mark the methods as final
If all variables are final, then it's kind of redundant to say that there should be no setters.
Also, these are sufficient constraints, but not necessary. You can for instance have immutable classes without final variables / final field types as long as they are private, never changed internally and never leaked to outsiders.

If i do have setters also,i cannot change the state of the Object, As
i have all the final variables. so how will this affect immutablity.
final is at reference level and immutability is at instance level.
class someMutableClass{
final List someList;
}
In the above piece of code. If the reference of the list escapes, then anyone can do :
someList.add(someValue)
But they cannot do :
someList=someOtherList;
That is the difference.
how can inheritence change the object state in this case?
The child class can access certain fields of the parent class and then change it. You can can make a parent class reference point to a child class object and modify its fields. So, to ensure immutability, you have to ensure that the child class doesn't alter anything in the parent. So make it final.

An immutable class is one that you cannot change. Achieving immutability is a matter of eliminating possible ways of changing an object's state. That can be achieved by a combination of structural and behavioural means.
But first, lets look at the "should have" list:
"class should be final" - This may be advisable, but it may not be strictly necessary ... or even desireable. An instance1 of a class can be immutable even if instances of some subclasses are mutable. It all depends on which classes need to be immutable, and that depends on the context.
"all the methods should be final" - Neither necessary or sufficient. If the class is final then it is unnecessary. If the class is NOT final, then it is not sufficient. (You can add methods with different signatures in a subclass.)
"all the variables should be final" - Neither necessary or sufficient. You can have an immutable class whose fields are not final, and a mutable class whose fields are all final.
"there should not be any setters" - It depends on what you mean by a "setter", but once again this is neither necessary (for some models of mutability) or sufficient.
Your Questions:
1) What if i have a class with only final variables ?
That is not sufficient to guarantee immutability. For example, if one of the final variables is an array, then the state of that array could be changed, thereby changing the state of the object as a whole. This could be done by a setter (or any other method of the class), or if the class is a "leaky abstraction" then it could done by external code.
2) If i do have setters also,i cannot change the state of the Object, As i have all the final variables. so how will this affect immutablity.
See above. Declaring all fields as final is not a guarantee of immutability. A setter could change the state of a mutable component of the object.
3) how can inheritence change the object state in this case?
It can't1. But that's not the point.
The reason for making an immutable class final is to stop someone creating a mutable subclass of the class.
Why does that matter?
Well, suppose that a method requires parameters to be immutable (e.g. for security). If you declare it with an immutable class that is not final, then someone create an mutable subclass and pass an instance of that instead of the original immutable class.
This is the main reason why (for example) the String class is final.
1 - I need to qualify this. It depends on whether we are talking about instances whose class is A, or about instances that are type compatible with A. I'm talking about the former. The fact that there is a mutable subclass does affect the mutability of an instance whose class is A.

Related

How to make the return immutable in JAVA

I have an object such as
public class ABC {
private String a;
private String b;
private String c;
//getters and setters
}
This object is returned from a method in the collections such as ArrayList<ABC>.
I just want to make the return immutable without changing anything in the object. Can anyone please help me with this?
Don't provide setters (mutators), make immutable attributes private, only provide value assignment via constructor.
You can always declare your immutable attributes final. So you can only assign them values once and can't change them later.
You cannot make an object immutable if its class provides for mutation. Objects always offer all the capabilities defined by their classes.
Therefore, if you want an immutable object then you need an immutable class. If you cannot change the class in question, then a wrapper class such as #duffymo described could serve that purpose. Note, however, that objects of such a class are not interchangeable with objects of the wrapped class, and also that somehow you need to provide for applying the wrappers.
If you need objects that are fully interchangeable with objects of class ABC, then you're stuck with the fact that ABCs are mutable, therefore anything interchangeable with ABCs is mutable, at least with respect to the mutable aspects of ABC. Then it comes down to why you want immutability. If the point is to avoid mutating the object referenced by the List, then copying those objects (to whatever depth is appropriate) is an alternative.
As a third alternative, if the target class has no non-private fields then you might be able to create a subclass, overriding the setters to be ineffective or to throw some variety of unchecked exception. In that case, note that
Such a subclass is not good form, and its instances are not truly interchangeable with instances of class ABC.
If class ABC has accessible properties of mutable types (e.g. mutable containers), then you may need to do something to prevent those objects from being mutated, too. Recursively.
Yes, this is a big mess.
Use interfaces with only getters
A is your concrete (impl) class
Coding to interfaces?
public I getA(){ retrun AImpl();}
where
public interface I { public String getOne()}
public AImple implements I {...}
The only "Change" in your current class would be "implements I"
JDK and Apache commons use decorators
http://grepcode.com/file/repository.jboss.org/nexus/content/repositories/releases/org.jboss.embedded/thirdparty-all/beta3.SP15/org/apache/commons/collections/list/UnmodifiableList.java
Another solution
Clone your object and return it, that way copy is changed and original object remains intact

Is this object mutable?

If I have a class like that:
public class MyObject {
private int myField = 2;
public void setMyField(int f) {
this.myField = f;
}
}
Will objects of this class be mutable?
Thanks!
Of course - if you want it to be immutable, then you need something like:
public class MyObject {
private final int myField;
public MyObject(int f) {
myfield = f;
}
public int getMyField() {
return myField;
}
}
yes
Mutable objects have fields that can be changed, immutable objects
have no fields that can be changed after the object is created.
You already have several answers with a "Yes".
I would like to add a "but" (if I would be bold, I would say "No" ;-)
Yes, an object of this class appears to be mutable, since it provides a setter to change the field. However, since it does not have a getter for that field, neither any other getter depending on that field, and since the field is private, it is currently not possible to read that state.
Put differently: The object has state, but it does not expose any state to the outside.
I would call that object "effectively immutable".
There are some design patterns, where objects are "effectively immutable", for example "Lazy Initialization" of an "Immutable Object".
Note: The concept of being "effectively immutable" is discussed in Section 3.5.4 of Java Concurrency in Practice by Brian Goetz.
Yes, objects of this class are mutable. The designer of the class can't prohibit by any technical means (in real existing Java) consumers of the objects to observe and modify the contents of the field.
private is an explicitly declared contract regarding intended usage of the field - this contract can be broken, e.g. with reflection.
Not providing any methods that change the data of an object after creation can also be a (implicitly declared) contract about intended use and mutability - this contract, too, can be broken, like any contract that needs two conforming parties.
Edit: Unless there is another party that has the means to enforce - like in Java the SecurityManager stopping you from changing a final field at runtime.
Yes, your object is mutable as the value of myField can be changed after the instance is created using the setter.
Immutability can be achieved using final fields, as it will not allow you to change the value of a variable once it is initialized.
Answer by #JakubK points out how you can make your class Immutable.
But declaring reference final wont make the object being pointed by it final.
For example:
class MyObject{
private final List<Integer> list = new ArrayList<Integer>();
public List<Integer> getList(){
return list;
}
}
I can change add a new element to the list from outside by doing something like this
instance.getList().add(1); //mutates the list
This example is not immutable, as the List can be changed by someone else.
To define whether something is mutable, one has to define what state is encapsulated thereby. If MyObject specifies that its state includes the value which Reflection will report for myField, then it is mutable. If that field is not specified as being part of the object's observable state, then it may be most purposes regarded as immutable.
To be more specific, I would regard a class as being immutable only if one could perform any combination of documented operations upon the class, in any sequence and with any timing (even on multiple threads), and not have any documented behavioral aspects of of any of them affected by any other. The fact that a method might change the contents of a private field is relevant if and only if that change would affect some documented behavioral aspect of another method call (to the same or different method). For example, I would say that the fact that String.hashCode() modifies the hash field does not make String mutable, because the value returned by hashCode() is not affected by whether or not the field had been written previously. If a class had a hashCode method which would, if a field was blank, generate a random number and store it in that field, and otherwise return the value directly, such a class would be mutable unless it ensured that the field was tested and set as an atomic operation. In the absence of such assurance, it would be possible for near-simultaneous calls to hashCode() to yield different values, and thus for future calls to differ values that would differ from at least one of them (implying that the object's state had changed between the call that returned the odd-ball value and the later call).

Class variable: public access read-only, but private access r/w

In my current project I have a class which stores its Instance in a variable. This Instance should be accesible by all other classes in the project, but it may only be altered by its own class.
How can I achieve this?
Write a public getter but no public setter. And the field itself private
In short that is called immutable object, state of Object cannot change after it is constructed.
String is a common example of immutable Class.
Make a class immutable by following-
ensure the class cannot be overridden - make the class final, or use
static factories and keep constructors private.
make fields private and final
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.
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.
Someone suggests "public getter but no public setter for the private field."
Caution: This would only work if the field is primitive type.
If it is an object with setters, the content can still be modified; thus not read-only.
It will be interesting to see Java language provide some constructs to make a return type read-only without having to do a deep-copy / clone.
i'm imaging like
ReadOnly getEmployee() {
...}
The boilerplate code for instantiating a singleton can be found in many places, see for example http://www.javacoffeebreak.com/articles/designpatterns/index.html
Be aware that many consider the singleton to be an antipattern because it's pretty hard to get rid of once your application is littered with references to the singleton.

Is It Immutable Class?

Does this below class is immutable?
class Immutable {
private int x;
Immutable(int value) {
this.x = value;
}
public int getX(){
return x;
}
}
Class is not final Since no member is visible to sub class
Instance Variable x is not final since there is no setter method.
Is there any possiblity this class will break the contract of Immutable functionality without adding any code in this class?
The class is practically immutable.
But you can still use reflection to set the value of the variable x since the variable is not final.
The Immutable class is immutable.
However, it is possible to declare a subclass of Immutable whose instances are mutable. Indeed, the only way to prevent this is to make this class final ... or make its constructor private.
You could argue (and I would) that a mutable subclass of Immutable is violating the contract of Immutable.
The approach of changing the value of x using reflection is breaking the rules. The Java specs say that the behavior of an application that does this is unspecified. (Certainly, it breaks all sorts of assumptions that the JLS says that the JIT compiler is allowed to make.)
A sensible developer won't do that kind of thing, will discount the possibility of someone else doing it, and will say that Immutable is immutable despite the theoretical possibility that some total lunatic could change it.
Joshua Bloch in his "Effective Java" states that "you should either design your classes for extensibility or make them non-extensible".
If flexibility is your primary concern and you have a strong reason to design your immutable class for inheritance - leave this class non-final.
If security is your concern - make this class final and member field final. Because:
Non-final classes can be extended to create a mutable child classes by overriding getter method.
Java is reflective by design. As Belgther told it's possible to set the value of member field using reflection. (no matter private or public) A long time ago I used this to integrate my specific debugger with another project.
Yes, it seems to me that it's immutable.
Since you have a private field that can only be set in the constructor and the only method in that class is a getter, then that field cannot be modified anymore, and the class can be said immutable.

Java immutable-class rules

Is the below class immutable:
final class MyClass {
private final int[] array;
public MyClass(int[] array){
this.array = array;
}
}
No it is not because the elements of the array can still be changed.
int[] v1 = new int[10];
MyClass v2 = new MyClass(v1);
v1[0] = 42; // mutation visible to MyClass1
My two cents regarding immutability rules (which I retained from reading Effective Java - a great book!):
Don't provide methods that can modify the state of an object.
Make all your fields final.
Make sure that your class is non-extendable.
Make all your fields private.
Provide exclusive access to any fields or components of your class that can be changed. Essentially this applies to your situation (as explained by JaredPar). A person that uses your class still has a reference to your array. The opposite is the case where you return a reference to an component of your class. In this case, always create defensive copies. In your case, you should not assign the reference. Instead, copy the array that the user of your class provides, into your internal component.
"Immutability" is a convention between the programmer and himself. That convention may be more or less enforced by the compiler.
Instances of a class are "immutable" if they do not change during the normal course of the application code execution. In some cases we know that they do not change because the code actually forbids it; in other cases, this is just part of how we use the class. For instance, a java.util.Date instance is formally mutable (there is a setTime() method on it) but it is customary to handle it as if it were immutable; this is just an application-wide convention that the Date.setTime() method shall not be called.
As additional notes:
Immutability is often thought of in terms of "external characteristics". For instance, Java's String is documented to be immutable (that's what the Javadoc says). But if you look at the source code, you will see that a String instance contains a private field called hash which may change over time: this is a cache for the value returned by hashCode(). We still say that String is immutable because the hash field is an internal optimization which has no effect visible from the outside.
With reflection, the most private of instance fields can be modified (including those marked as final), if the programmer wishes so hard enough. Not that it is a good idea: it may break assumptions used by other pieces of code using the said instance. As I said, immutability is a convention: if the programmer wants to fight himself, then he can, but this can have adverse side-effects on productivity...
Most Java values are actually references. It is up to you to define whether a referenced object is part of what you consider to be "the instance contents". In your class, you have a field which references an (externally provided) array of integers. If the contents of that array are modified afterwards, would you consider that this breaks immutability of your MyClass instance ? There is no generic answer to that question.
There is no way to make an array immutable. That is there is no way to keep any client code from setting or removing or adding items to the array.
Here is a truly immutable alternative:
private static class MyClass
{
private List<Integer> list;
private MyClass(final int[] array)
{
final List<Integer> tmplist = new ArrayList<Integer>(array.length);
for (int i : array)
{
tmplist.add(array[i]);
}
this.list = Collections.unmodifiableList(tmplist);
}
}
To make a class immutable, you need to both ensure that all the fields on it are final, and that the types of those fields are immutable too.
This can be a pain to remember, but there is a tool to help you.
Pure4J provides an annotation #ImmutableValue, which you can add to an interface or class.
There is a maven plugin to check at compile-time that you are meeting the rules on immutability following this.
Hope this helps.

Categories

Resources