No mutator methods • Exclusive access to mutable components (ref guarding) • Final class • Object creation is hard! (constructors, toString, hashcode…)
is at the heart of creating good applications and services, and of good design in general” • Immutable objects - Constructed once, in a consistent state and can be shared • Mandatory attributes - Will fail if they are missing • No sneaky modifications - When passed to other code • Naturally thread safe • Object definitions are pleasant to write and read • No boilerplate setter and getters • Clean code - based off of tenets of Effective Java
applies serial version to enclosing types • @Serial.Structural - enables structural serialization so you can evolve your data • Using above annotations will cause generated objects to impl java.lang.Serializable • Just include: org.immutables:serial:2.2.5
values of attributes you want to change Value changedValue = ImmutableValue.copyOf(existingValue) .withName("Changed Name") .withValues(Arrays.asList("Only new value")) .build(); @Value.Immutable public interface Value { String name(); String address(); List<String> values(); }
values of attributes you want to change List<Classroom> classrooms = ImmutableList.<Classroom>builder() .addAll(school.classrooms()) .add(newClassroom) .build(); school = ImmutableSchool.copyOf(school).withClassrooms(classrooms);
generated code @Value.Style( get = {"is*", "get*"}, // Detect 'get' and 'is' prefixes in accessor methods init = "set*", // Builder initialization methods will have 'set' prefix typeAbstract = {"Abstract*"}, // 'Abstract' prefix will be detected and trimmed typeImmutable = "*", // No prefix or suffix for generated immutable type builder = "new", // construct builder using 'new' instead of factory method build = "create", // rename 'build' method on builder to 'create' visibility = ImplementationVisibility.PUBLIC, // Generated class will be always public defaults = @Value.Immutable(copy = false)) // Disable copy methods by default