Before concretizing my question, let me provide some background: My main programming languages are C++ and Java. When working with C++ I find it important to apply const correctness, that is declaring functions like this:
A::DoSomething( const B& arg ); // guarantees that arg is not modified
A::DoSomething() const; // guarantees that the object of type A is not modified
A::DoSomething( const B& arg ) const; // both of the above
In fact, I often wish that const
would be the default and objects that are modified have to be marked somehow.
My main reasons for using const
are:
It is well-known that Java has no const
keyword (you can't do the above with final
) and this fact has been discussed here before, see for example here: Equivalent of const(C++) in Java.
The Java alternative that is usually proposed is to make your classes immutable. While this is not a full replacement of const
because it works per class and not per context in which a class is used, it would work fine for me in most cases.
But there is one big issue with immutable classes: Immutability is not obvious. To find out if a class really is immutable, as far as I know, you basically have to check the full source code. Any method could have a backdoor through which the object could be modified.
So is there an easier way to check immutability? Or is there any best practice to somehow mark a class as being immutable?
Note: I know that both languages provide 'evil tricks' to bypass constness or immutability: C++ has const_cast
and Java has reflection. But for the context of my question, let's assume that these are not used.
At a fundamental level: immutable classes define objects which, once created, never change their value. A variable of an immutable type may only be changed by re-assigning to that variable. When we wish to only modify some portion of an immutable class, we are compelled to reassign the whole object.
Immutable class in java means that once an object is created, we cannot change its content. In Java, all the wrapper classes (like Integer, Boolean, Byte, Short) and String class is immutable.
In Java, when we create an object of an immutable class, we cannot change its value. For example, String is an immutable class. Hence, we cannot change the content of a string once created.
The immutable objects are objects whose value can not be changed after initialization. We can not change anything once the object is created. For example, primitive objects such as int, long, float, double, all legacy classes, Wrapper class, String class, etc. In a nutshell, immutable means unmodified or unchangeable.
Java has no first-class immutability support, so you have no reliable way to detect if class is immutable.
Java Concurrency In Practice recommends (see Appendix A as reference) to use class-level @Immutable
annotation from javax.annotation.concurrent
and this is the most convenient, common and standard way to indicate immutability; custom javadoc is fine too. Note that it's only declaration, not actual constraint.
Design of the class is also a good indicator:
this
reference doesn't leak from constructor)Full list of immutable class design properties can be found in Oracle tutorials.
So, to check if class is immutable you first look at class level annotations and javadoc and only then at implementation itself.
To provide additional sanity-check (if you think that annotated as immutable class can be mutable by mistake), there is Mutability Detector plugin for FindBugs (static analysis tool), which effectively doing same thing listed above: checks class has @Immutable
annotation and verifies (via reflection) that all immutability rules are satisfied (with some additional things like immutable collection support from Guava etc.). Mutability detector also can be used as library without FindBugs, which allows you to write tests like that:
@Test
public void testImmutable() {
assertImmutable(MyClass.class);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With