First in the series #stealbackfromai
you need validation for record or default values ?
I was silly trying this to define default values in a record:
public static record SomeCounts(UUID id, Long v1, Long v2, Long v3){
SomeCounts(UUID id, Long v1, Long v2, Long v2){
this(id,
v1== null ? 0l : v1,
v2== null ? 0l : v2,
v3== null ? 0l : v3
);
}
}
It does not compiple (Canonical constructor cannot delegate to another constructor). Turns out there is nicer and cleaner way already provided called comapct constructor.
Compact constructors
Compact constructors in Java records provide a concise way to customize the canonical constructor (the default one matching the record's components) without repeating parameter names.
Syntax Basics
Declare it immediately after the record header, using just the record name in braces—no parameter list needed:
public static record SomeCounts(UUID id, Long v1, Long v2, Long v3){
public SomeCounts{
v1 = v1== null ? 0l : v1,
v2 = v2== null ? 0l : v2,
v3 = v3== null ? 0l : v3
// Validation example:
//if (id == null) throw new IllegalArgumentException();
}
}
The compiler implicitly supplies parameters matching the fields and handles field assignments after your body executes.12
Execution Flow
- Your compact body runs first (for validation/normalization).
- Compiler auto-assigns parameters to
finalfields. - Superclass
Recordconstructor completes.
You can modify parameters (like null checks), throw exceptions, or print logs, but cannot assign fields directly (this.v1 = ... fails compilation).3
Key Benefits
-
Zero boilerplate: No need to write
this.field = field;everywhere. -
Immutable safety: Fields stay
final; changes only affect incoming parameters before final assignment. - Canonical only: Applies to the main constructor; doesn't affect static factories or other overloads.
Common Patterns
| Use Case | Example Code |
|---|---|
| Null-to-default |
v1 = (v1 != null) ? v1 : 0L; 4
|
| Range validation |
if (v3 < 0) throw new IllegalArgumentException(); 5
|
| Normalization |
id = id.toString().toLowerCase(); 5
|
This keeps your record cleaner while ensuring numeric fields are never null post-construction.1678910
-
https://blogs.oracle.com/javamagazine/post/java-record-compact-canonical-constructor ↩
-
https://docs.oracle.com/en/java/javase/16/language/records.html ↩
-
https://stackoverflow.com/questions/74083123/java-record-compact-constructor-bytecode ↩
-
https://mikemybytes.com/2022/02/16/java-records-and-compact-constructors/ ↩
-
https://www.reddit.com/r/java/comments/stte7o/java_records_compact_constructors/ ↩
-
https://stackoverflow.com/questions/77582274/throw-exception-in-records-compact-constructor ↩
-
https://coderanch.com/t/754107/certification/understand-Records-comapact-constructor-overloaded ↩
SOCIAL SHARE CARD GENERATOR