Careeroza
Compact Constructors and Methods
Validation in a Compact Constructor
A compact constructor has no parameter list. It runs before the fields are assigned, so you can validate or normalise the parameters.
Example
public class Main {
record Email(String value) {
Email { // compact constructor
if (value == null || !value.contains("@")) {
throw new IllegalArgumentException("Invalid email: " + value);
}
value = value.strip().toLowerCase(); // normalise before assignment
}
}
record Money(long paise) {
Money {
if (paise < 0) throw new IllegalArgumentException("negative amount");
}
static Money ofRupees(double rupees) { // static factory
return new Money(Math.round(rupees * 100));
}
Money plus(Money other) { // records can have methods
return new Money(paise + other.paise);
}
@Override
public String toString() {
return String.format("Rs %d.%02d", paise / 100, paise % 100);
}
}
public static void main(String[] args) {
System.out.println(new Email(" [email protected] "));
System.out.println(Money.ofRupees(199.5).plus(Money.ofRupees(0.75)));
try {
new Email("not-an-email");
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}Output
Email[[email protected]] Rs 200.25 Invalid email: not-an-email
Immutability and with-style Copies
Example
Record fields are final. To "change" one, create a new record. A small withX method makes this convenient.
public class Main {
record Address(String city, String pin) {
Address withCity(String newCity) {
return new Address(newCity, pin);
}
}
public static void main(String[] args) {
Address home = new Address("Pune", "411001");
Address moved = home.withCity("Mumbai");
System.out.println(home);
System.out.println(moved);
}
}Output
Address[city=Pune, pin=411001] Address[city=Mumbai, pin=411001]
Note: A record is only shallowly immutable. A List component can still be modified unless you copy it with List.copyOf in the compact constructor.