I'm currently developping a multithreaded framework. To avoid side effects, I would like to require that all data manipulated by the framewok has to be immutable.
So does a way exist in Java to specify I want all subclasses of a given class or all classes implementing a given interface to be immutable?
To make a class truly immmutable, all members of the class must be immutable and the class itself must be
final
. This ensures the object cannot be changed from within the class or outside of the class.To make members inside the class immutable, this means more than just making them
final
. For examplestrings
isfinal
but can still be changed because items can be added and removed from the list. In this case, you could wrap it in an unmodifiable collection. Even this is not perfect though because the objects in your list could be mutable (Strings
are not obviously, but your list might have mutable objects in them where you could dolist.get(index).mutator(...)
)There is no silver bullet as to how to make an object immutable. If it provides any methods that mutate the object, then it cannot be immutable.
As for making a class
final
, to achieve guaranteed immutability this necessary. Imagine the case,There is no guarantee that
doSomething
is actually dealing with an immutable instance but rather it could be dealing with a mutable subclass. As you can see, this would pose a problem for working with interfaces. There is no way to guarantee that an implementor of an interface is immutable.The
@Immutable
annotation does not guarantee immutability, but rather just states that the class is telling you it is immutable, but there is no good way to enforce that.If you are able to work in groovy the
@Immutable
annotation has some effect as it does a lot of these techniques above that I mentioned. http://groovy.codehaus.org/Immutable+AST+MacroI recommend looking into Mutability Detector. It performs static analysis to determine if a given class is immutable. It could be used to add something akin to a runtime assertion, i.e. you could choose to throw an exception if you are passed an instance of a mutable class. Note that it could analyse the actual, concrete class at runtime, including subclasses or implementations of an interface that you have defined.
It is still a pre-1.0 release, and has issues with
java.lang.String
, but it could be usable. If it's close to what you're looking for, but doesn't quite do what you want, I recommend contacting the mailing list or filing a bug report, as I believe the project maintainer is quite a reasonable guy. Disclaimer: that maintainer is me ;-)There is no way to require immutability of subclasses. You can make sure that subclasses of your classes do not mutate your state by not providing setters and keeping your instance variables private, but if subclasses declare their own instance variables, they have full control over them.
As far as interfaces go, the only thing you can do is to not provide setters. However, implementations can provide setters of their own.