https://www.baeldung.com/introduction-to-autovalue
@AutoValue
public abstract class AutoValueMoney {
public abstract String getCurrency();
public abstract long getAmount();
public static AutoValueMoney create(String currency, long amount) {
return new AutoValue_AutoValueMoney(currency, amount);
}
}
What has happened is that we write an abstract class, define abstract accessors for it but no fields, we annotate the class with @AutoValue all totalling to only 8 lines of code, and javac generates a concrete subclass for us which looks like this:
public final class AutoValue_AutoValueMoney extends AutoValueMoney {
private final String currency;
private final long amount;
AutoValue_AutoValueMoney(String currency, long amount) {
if (currency == null) throw new NullPointerException(currency);
this.currency = currency;
this.amount = amount;
}
// standard getters
https://mincong-h.github.io/2018/08/21/why-you-should-use-auto-value-in-java/
A value type is class without identity: two instances are considered interchangeable as long as they have equal field values
AutoValue
public abstract class Transaction {
public static Transaction of(long id, String user) {
return new AutoValue_Transaction(id, user);
}
public abstract long id();
public abstract String user();
}
Behind the scenes, Auto Value generates all the private fields, the constructor,
hashCode()
, equals()
, and toString()
for you. The generated class always starts with “AutoValue_“, more explicitly, it naming convention is AutoValue_<MyClass
I would also summary it as a comparison table:
Item | Without AutoValue | AutoValue |
---|---|---|
Auto attr declaration | N | Y |
Auto getters | N | N |
Auto toString() | N | Y |
Auto hashCode() | N | Y |
Auto equals() | N | Y |
Immutable | Y (*) | Y |
Auto update toString() | N | Y |
Auto update hashCode() | N | Y |
Auto update equals() | N | Y |
@AutoValue
public abstract class Transaction {
public static Builder builder() {
return new AutoValue_Transaction.Builder();
}
public abstract long id();
public abstract String user();
@AutoValue.Builder
public abstract static class Builder {
abstract Builder id(long id);
abstract Builder user(String user);
abstract Transaction build();
}
}
When using it, you can do:
Transaction t = Transaction.builder().id(1).user("foo").build();
AutoValue is the only solution to the value class problem in Java having all of the following characteristics:
- API-invisible (callers cannot become dependent on your choice to use it)
- No runtime dependencies
- Negligible cost to performance
- Very few limitations on what your class can do
- Extralinguistic "magic" kept to an absolute minimum (uses only standard Java platform technologies, in the manner they were intended)
https://docs.google.com/presentation/d/14u_h-lMn7f1rXE1nDiLX0azS3IkgjGl5uxp5jGJ75RE/edit#slide=id.g2a5e9c4a8_0104
With Lombok, a class with @Value need only declare fields. Lombok hacks the Java compiler to insert the constructor, getters, equals, hashCode, and toString into the class as it is compiled.
- Pros:
- Maximally concise value classes.
- Cons:
- The inserted code is invisible. This makes for a poor experience with tools, such as debuggers and code explorers.
- The compiler hacks are non-standard and fragile.
- Lombok functions outside the boundaries of how things work in Java. It is extralinguistic. This is a dangerous line to cross that is sure to cause confusion.