Generated immutable value classes for Java 8+ using annotation processing
—
AutoValue generates immutable value classes that automatically implement equals(), hashCode(), and toString() methods with proper value semantics. Value classes are defined as abstract classes with abstract property getter methods.
@AutoValue
public abstract class BasicExample {
public abstract String name();
public abstract int age();
public static BasicExample create(String name, int age) {
return new AutoValue_BasicExample(name, age);
}
}The generated class AutoValue_BasicExample will:
BasicExample person = BasicExample.create("Alice", 30);
BasicExample samePerson = BasicExample.create("Alice", 30);
BasicExample differentPerson = BasicExample.create("Bob", 25);
System.out.println(person); // BasicExample{name=Alice, age=30}
System.out.println(person.equals(samePerson)); // true
System.out.println(person.equals(differentPerson)); // false
System.out.println(person.hashCode() == samePerson.hashCode()); // trueAutoValue supports all Java types as properties:
@AutoValue
public abstract class TypesExample {
// Primitives
public abstract int intValue();
public abstract long longValue();
public abstract boolean booleanValue();
public abstract double doubleValue();
// Object types
public abstract String stringValue();
public abstract List<String> listValue();
public abstract Optional<Integer> optionalValue();
// Custom types
public abstract CustomClass customValue();
// Arrays
public abstract String[] arrayValue();
public static TypesExample create(
int intValue,
long longValue,
boolean booleanValue,
double doubleValue,
String stringValue,
List<String> listValue,
Optional<Integer> optionalValue,
CustomClass customValue,
String[] arrayValue) {
return new AutoValue_TypesExample(
intValue, longValue, booleanValue, doubleValue,
stringValue, listValue, optionalValue, customValue, arrayValue);
}
}Properties can be marked as nullable using any annotation named "Nullable":
@AutoValue
public abstract class NullableExample {
@Nullable
public abstract String nullableProperty();
public abstract String requiredProperty();
public static NullableExample create(@Nullable String nullableProperty, String requiredProperty) {
return new AutoValue_NullableExample(nullableProperty, requiredProperty);
}
}AutoValue supports generic type parameters:
@AutoValue
public abstract class GenericExample<T, U> {
public abstract T firstValue();
public abstract U secondValue();
public static <T, U> GenericExample<T, U> create(T firstValue, U secondValue) {
return new AutoValue_GenericExample<>(firstValue, secondValue);
}
}AutoValue classes can implement interfaces and extend abstract classes:
public interface Identifiable {
String getId();
}
@AutoValue
public abstract class IdentifiableEntity implements Identifiable {
@Override
public abstract String getId();
public abstract String name();
public static IdentifiableEntity create(String id, String name) {
return new AutoValue_IdentifiableEntity(id, name);
}
}You can add custom methods to AutoValue classes:
@AutoValue
public abstract class PersonWithMethods {
public abstract String firstName();
public abstract String lastName();
public abstract int age();
// Custom method
public String fullName() {
return firstName() + " " + lastName();
}
// Custom predicate
public boolean isAdult() {
return age() >= 18;
}
public static PersonWithMethods create(String firstName, String lastName, int age) {
return new AutoValue_PersonWithMethods(firstName, lastName, age);
}
}Control which annotations are copied to the generated implementation:
@AutoValue
@CopyAnnotations // Copy class-level annotations
public abstract class AnnotatedExample {
@CopyAnnotations
@SuppressWarnings("example")
public abstract String annotatedProperty();
@CopyAnnotations(exclude = {Deprecated.class})
@Deprecated
@SuppressWarnings("example")
public abstract String selectivelyAnnotatedProperty();
public static AnnotatedExample create(String annotatedProperty, String selectivelyAnnotatedProperty) {
return new AutoValue_AnnotatedExample(annotatedProperty, selectivelyAnnotatedProperty);
}
}Add validation to factory methods:
@AutoValue
public abstract class ValidatedExample {
public abstract String email();
public abstract int age();
public static ValidatedExample create(String email, int age) {
checkArgument(email.contains("@"), "Invalid email: %s", email);
checkArgument(age >= 0, "Age must be non-negative: %s", age);
return new AutoValue_ValidatedExample(email, age);
}
private static void checkArgument(boolean condition, String message, Object... args) {
if (!condition) {
throw new IllegalArgumentException(String.format(message, args));
}
}
}AutoValue works well with immutable collections:
@AutoValue
public abstract class CollectionExample {
public abstract ImmutableList<String> items();
public abstract ImmutableSet<Integer> values();
public abstract ImmutableMap<String, Object> properties();
public static CollectionExample create(
Iterable<String> items,
Iterable<Integer> values,
Map<String, Object> properties) {
return new AutoValue_CollectionExample(
ImmutableList.copyOf(items),
ImmutableSet.copyOf(values),
ImmutableMap.copyOf(properties));
}
}AutoValue generated constructors validate non-null parameters:
// This will throw NullPointerException
PersonExample person = PersonExample.create(null, 25); // NPE: name cannot be null
// Use Optional for nullable values instead
@AutoValue
public abstract class SafeExample {
public abstract Optional<String> optionalName();
public abstract int age();
public static SafeExample create(@Nullable String name, int age) {
return new AutoValue_SafeExample(Optional.ofNullable(name), age);
}
}Install with Tessl CLI
npx tessl i tessl/maven-com-google-auto-value--auto-value