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.