Search code examples
javaimmutabilityfinal

Immutable Java class with non-final member


I still have some problems grasping the idea of immutability in Java. I understand that it differs from the const-ness in C++ and that a final class that only has final members of classes that are immutable themselves is immutable. E.g. the following class is immutable:

public final class A {
    final String x;
    final int y;

    public A(String x, String y) {
        this.x = x;
        this.y = y;
    }
}

Is there some formal definition besides the guidelines presented here and similar stuff somewhere else?

Consider the following example. Is Person immutable? Is there a way to make it immutable besides making the members mother and father final. I cannot make them final because I have to build a list of People objects from an input file with arbitrary sorting and do not want to perform topological sort on this input. Also, the case of cycles should be possible to be represented.

public final class Person {
    Person father = null;
    Person mother = null;
    public final String name;

    Person(String name) { this.name = name; }

    public Person getFather() { return father; }
    public Person getMother() { return mother; }
}

// in the same package

public class TrioBuilder {
    // build trio of child, mother, and father
    public static ArrayList<Person> build(String c, String m, String f) {
        Person child = new Person(c);
        Person mother = new Person(m);
        Person father = new Person(f);

        child.father = father;
        child.mother = mother;

        ArrayList<Person> result = new ArrayList<Person>();
        result.add(child);
        result.add(mother);
        result.add(father);
        return result;
    }
}

Solution

  • Is Person immutable?

    No it isn't.

    An immutable class is final and only has final members.

    In your case, what you want to use is a builder class:

    final Person person = new PersonBuilder().withFather(xx).withMother(xx).build();
    

    This way you can make all members of Person final, and since Person is itself final, you get a real immutable class.