Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find out if a class is immutable

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 constare:

  • Communication with other developers: It makes code more expressive.
  • Communication with the compiler: It helps to find issues at compile time and sometimes makes additional optimizations possible.

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.

like image 300
Frank Puffer Avatar asked May 07 '16 11:05

Frank Puffer


People also ask

What makes a class immutable?

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.

Which one of the class is immutable?

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.

What is a good example of an immutable class?

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.

What is immutable with examples?

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.


1 Answers

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:

  • Have only final fields (but in rare cases it's possible to have some non-final fields and still be immutable, for example see String#hashCode)
  • It's properly constructed (this reference doesn't leak from constructor)
  • Object state cannot be modified (so class should not have setters and mutator methods)
  • Don't store external (passed to constructor) references to mutable objects (e.g. create defensive copy of passed collection argument)

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);
}
like image 197
qwwdfsad Avatar answered Sep 28 '22 06:09

qwwdfsad