Is a class generated with @AutoValue immutable? Can I use it instead of creating the class myself and making sure it can be annotated @Immutable?
1 Answers
AutoValue is advertised as "Generated immutable value classes for Java 7+". But if you use mutable fields, the AutoValue class is not @Immutable, that is, does not follow the contract defined in the annotation javadoc. This is clearly pointed out in the Autovalue docs.
Further, if you declare a property in an AutoValue class that is a Collection, like
public abstract Map<String, ImmutableThing> thingMap();
The resulting field is not necessarily immutable, it depends on what implementation of Map you pass into the constructor. For immutability, you want to use something like ImmutableMap instead, which forces you to pass in an ImmutableMap in the constructor:
public abstract ImmutableMap<String, ImmutableThing> thingMap();
It does seems to me that the generated AutoValue code could have automatically made collection properties like this immutable.
I imagine the @AutoValue designers had good reasons for their design, but the lack of immutability is surprising.

- 1,367
- 1
- 10
- 15
-
Only by replacing `java.util.Map` with `com.google.collections.ImmutableMap`. Given that guava (the library that has `ImmutableMap`) is aggressively backwards incompatible, automatically and silently doing that would be a grave API messup - you don't introduce silent surprises like that. In general, putting guava types in your public APIs (which you'd be doing with this move) is not a good idea. – rzwitserloot Jan 08 '21 at 14:55
-
Note also that this definition of immutable sounds like it is absolute, but it is not. It's just a guideline, and I can make you a mutable type which nevertheless adheres to every rule stated in both the javadoc and the autovalue docs. – rzwitserloot Jan 08 '21 at 14:56
-
@rzwitserloot, Im not sure if you're dissing the "@Immutable" spec, or saying that its impossible to make truly immutable objects? – John Caron Jan 08 '21 at 21:48
-
'dissing'? It's not a person, it's an API. The point is more that the definition of 'immutable' is a bit tricky. You can go the 'represents no state, or state that once set can never change' route (I'd call that one the useful route), or the 'all fields are final and, if reference types, to types that are themselves guaranteed immutable using the same definition' one. These are not quite the same definition, and you can make class defs that fit one but not the other. – rzwitserloot Jan 08 '21 at 22:05
-
A simple example: `java.io.File` is immutable according to the @Immutable rules, but not at all immutable for most commonly understood intents and purposes. For example, calling `.delete()` on one is neither memoizable nor idempotent. State is involved that can change - both by external entities and by invoking methods on this object. It's mutable for all practical intents and purposes. And yet, `@Immutable`, according to the spec. Just one example of a few. It's hard to close this gap, and more about opinion and definitions than just encoding the obvious to tell the difference. – rzwitserloot Jan 08 '21 at 22:07
-
I would prefer "state once set can never change". I dont care about @Immutable per se. I care about code that works. – John Caron Jan 09 '21 at 14:26
-
... if you "dont care", why ask about it? AutoValue will eliminate the source of mutability that is non-final fields. It does nothing to guarantee a second source: Use of non-immutable reference values. It also does nothing against externally tracked state that is nevertheless observable, such as IdentityHashMaps and j.io.File. – rzwitserloot Jan 10 '21 at 01:54