Are Record fields final
This makes Record immutable by design.
🟢 Junior Level
Yes, all fields in Record are automatically final. This means they cannot be changed after the object is created.
public record User(String name, int age) {}
User user = new User("John", 25);
// ❌ Cannot change fields
user.name = "Jane"; // compilation error — field is final
// ✅ Can create a new Record
user = new User("Jane", 25); // OK
This makes Record immutable by design.
🟡 Middle Level
How it works
The compiler automatically makes all fields private final:
public record Point(int x, int y) {}
// Compiler generates:
public final class Point extends java.lang.Record {
private final int x; // implicit final
private final int y; // implicit final
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int x() { return x; }
public int y() { return y; }
}
Even if you don’t write final:
// Both options are identical
public record Point(int x, int y) {}
public record Point(final int x, final int y) {} // final is redundant
Important nuance: mutable components
Fields are final, but if they reference mutable objects, the contents can be changed:
public record User(String name, List<String> tags) {}
User user = new User("John", new ArrayList<>(List.of("admin", "user")));
// ❌ Cannot replace the list
// user.tags = new ArrayList<>(); // compilation error
// ✅ But can change the list contents
user.tags().add("moderator"); // OK! The list is mutable
user.tags().clear(); // OK!
Solution — defensive copy:
public record User(String name, List<String> tags) {
public User {
tags = List.copyOf(tags); // immutable list
}
}
User user = new User("John", List.of("admin"));
// user.tags().add("moderator"); // UnsupportedOperationException!
Common Mistakes
- Expecting full immutability: ```java public record Data(int[] values) {}
Data d = new Data(new int[]{1, 2, 3}); d.values()[0] = 99; // ✅ Can — array is mutable!
// ✅ Solution
public record SafeData(List
2. **Trying to change field:**
```java
public record Point(int x, int y) {
public void setX(int x) {
// this.x = x; // compilation error — final field
}
}
🔴 Senior Level
Internal Implementation
JVM level:
// All Record components have ACC_FINAL flag
Field {
access_flags: ACC_PRIVATE | ACC_FINAL
name: "x"
descriptor: "I"
}
Reflection confirms:
Field[] fields = Point.class.getDeclaredFields();
for (Field f : fields) {
System.out.println(f.getName() + " final=" + Modifier.isFinal(f.getModifiers()));
}
// Output: x final=true, y final=true
Architectural Trade-offs
Final fields:
| Pros | Cons |
|---|---|
| Thread-safe (safe publication) | Cannot change state |
| JIT optimizations | Need to create new objects |
| Predictability | Mutable components require protection |
| HashMap keys | Harder to work with graphs |
Edge Cases
1. Mutable components:
public record MutableRecord(Date createdAt) {}
MutableRecord r = new MutableRecord(new Date());
r.createdAt().setTime(0); // can change Date!
// ✅ Solution
public record ImmutableRecord(Date createdAt) {
public ImmutableRecord {
createdAt = new Date(createdAt.getTime()); // defensive copy
}
}
2. Final != immutable:
public record Config(Map<String, String> props) {}
// final field, but Map can be changed
Config c = new Config(new HashMap<>());
c.props().put("key", "value"); // OK
3. Memory visibility:
// final fields guarantee safe publication
// after constructor completes, all threads see correct values
public record SharedConfig(String url, int timeout) {}
// Publication safe
SharedConfig config = new SharedConfig("http://api.com", 5000);
// Another thread will see correct values
Performance
Final fields:
- JIT can inline values
- No need for volatile
- Safe publication without synchronization
- Memory barrier at construction
Benchmark:
// Approximate values. Depend on JVM/hardware.
Operation | Final fields | Mutable fields
-------------------|------------|-------------
Read | 1 ns | 1 ns
Publish (thread) | 0 ns | sync needed
JIT optimization | Maximum | Limited
Production Experience
Immutable DTO:
public record OrderDto(
String id,
Instant createdAt,
BigDecimal amount,
List<OrderItem> items
) {
public OrderDto {
items = List.copyOf(items); // protection against mutable collection
}
}
Value objects:
public record Money(BigDecimal amount, Currency currency) {
// Both fields are final — fully immutable
public Money add(Money other) {
// Return new object, don't modify current
return new Money(this.amount.add(other.amount), this.currency);
}
}
Best Practices
// ✅ Record for immutable data
public record User(String name, Email email) {}
// ✅ Defensive copy for mutable components
public record Tags(List<String> values) {
public Tags { values = List.copyOf(values); }
}
// ✅ Immutable collections
public record Config(Map<String, String> props) {
public Config { props = Map.copyOf(props); }
}
// ❌ Mutable components without protection
public record BadRecord(Date date, int[] array) {}
// ❌ Expecting that final = fully immutable
🎯 Interview Cheat Sheet
Must know:
- All Record fields are automatically
private final— compiler adds final - Final means you cannot replace the reference, but mutable objects inside can be changed
- Arrays, Date, collections — mutable components, require defensive copy
List.copyOf(),Set.copyOf(),Map.copyOf()to protect mutable collections- Final fields guarantee safe publication in multi-threaded environment (without volatile)
- JIT can better optimize final fields (inlining)
Common follow-up questions:
- Can you change an array inside Record? — Yes, arrays are mutable:
record.values()[0] = 99 - How to protect mutable component? — Defensive copy in compact constructor:
tags = List.copyOf(tags) - Final = fully immutable? — No, final only protects the reference, not the object contents
- Why is final important for HashMap keys? — Modified key = broken hashCode, data is lost
Red flags (DO NOT say):
- ❌ “Final means full immutability” — Mutable components can be changed
- ❌ “Array in Record is safe” — Arrays are always mutable, need defensive copy
- ❌ “Can change field via setter” — Fields are final, setter is impossible
- ❌ “Final gives no advantages” — Final gives safe publication and JIT optimizations
Related topics:
- [[1. What is Record in Java and since which version are they available]]
- [[5. What methods are automatically generated for a Record]]
- [[7. What is compact constructor in Record]]
- [[10. Can you use Record as a key in HashMap]]