Adding an @Immutable annotation to Java

Mariell Hoversholm mariell.hoversholm at paf.com
Thu Nov 25 09:49:30 UTC 2021


On Thu, 25 Nov 2021 at 10:03, Andrew Haley <aph-open at littlepinkcloud.com>
wrote:

> > Quick question, out of curiosity: how would it behave with respect to
> > inheritance? Can a @Immutable class inherit from an non immutable one?
>
> And: does @Immutable mean deeply immutable? IMO it really should,
> but that's harder to check, and we'd have to think about what this
> means for binary compatibility.
>

As cited in the original email,
> and the programmer could, for example, annotate a new record object with
@Immutable only if all its fields are annotated with @Immutable.

I would infer from this that it would mean deeply immutable.
To clarify further, the following record `Wrapper` would be legal only
because `A` has `@Immutable` on its _type_:

    @Immutable class A {}
    @Immutable record Wrapper(A a) {}

while this would not be legal:

    class A {}
    @Immutable record Wrapper(A a) {}

because `A` is not `@Immutable`. This could however borrow from the Rust
concept of "auto-traits" (read: automatically apply certain traits or
capabilities depending on how the type is defined), and infer `@Immutable`
if it is deeply immutable, but that would raise the question of API &
binary compatibility again.

It would also not be legal with this:

    @Immutable
    class A {
        private int value;
        public void value(int value) { this.value = value; }
    }

because `value` is _not_ immutable.

Moving on from your question, this then poses the question of memoizing
potentially very expensive optimisations, such as the following, currently
found in the JDK:
https://github.com/openjdk/jdk/blob/f0136ec94539d0e30ec11d44f8143196da1f7125/src/java.base/share/classes/java/lang/String.java#L2323-L2343
Code above from `java.base/java.lang.String`:

    public int hashCode() {
        // [snip large comment]
        int h = hash; // [hash is a property on the type]
        if (h == 0 && !hashIsZero) { // [hashIsZero is a property on the
type]
            h = isLatin1() ? StringLatin1.hashCode(value)
                           : StringUTF16.hashCode(value);
            if (h == 0) {
                hashIsZero = true;
            } else {
                hash = h;
            }
        }
        return h;
    }

If the compiler / JRE were to infer the immutability from setters, it would
again pose a new question of how to detect such. It could be possible that
adding a new keyword or annotation to ignore mutable fields would be
necessary (say `private mutable int hashCode;` as an example of my
thoughts). At that point, however, what is the difference to not having
this feature at all?

This is definitely an idea I like as a user of the language, but it's
something that would require a bit of work, assuming it can be boiled down
to something feasible at all.

-- 

*Mariell Hoversholm *(she/her)

Software Developer @ <https://aboutpaf.com>


More information about the core-libs-dev mailing list