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