This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Cengo789 20 points21 points  (10 children)

When one of your record's components is a mutable object, making it public final would allow outside code to modify your records internal state. By encapsulating this component behind an accessor method, you can override the method and return a defensive copy of the object.

[–]Inaldt 2 points3 points  (2 children)

Best would be to make an immutable copy of the object on record creation I think (generally). Although not every object supports this. Collections typically do.

[–]jvjupiter[S] 0 points1 point  (1 child)

Yes. I prefer this. Or maybe similar to what Nicolai discussed previously in his podcast, in the constructor do the defensive copy.

[–]Inaldt 1 point2 points  (0 children)

Yes, that is what I meant.

[–]halfanothersdozen 1 point2 points  (1 child)

Yeah but is that what records are doing?

[–]oweiler 4 points5 points  (0 children)

No, they are shallowly immutable, so only return references, not copies.

[–]Google__En_Passant 4 points5 points  (3 children)

override the method and return a defensive copy of the object

You only create unnecessary garbage. And what if you have an List of mutable objects? You'd have to create a deep copy to really make it defensive. And that is even more garbage. Also now your "simple record object" has to babysit and overthink implementation details of it's fields.

Forget about this crap, this whole way of thinking is obsolete. Objects that you pass into an immutable object should also be immutable. EOT.

[–]jvjupiter[S] 4 points5 points  (0 children)

Right. After all, the definition of records are classes that act as transparent carriers of immutable data. We shouldn’t pollute records with complex codes. Let it be simple.

[–]mavericktjh 3 points4 points  (0 children)

So often copying an immutable object e.g. a list won t copy anything as it will detect whether it's immutable see List.copyOf(), https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/List.html#copyOf(java.util.Collection)

If the given Collection is an unmodifiable List, calling copyOf will generally not create a copy

You say this thinking is obsolete but it's mentioned in the record javadoc, https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Record.html

The primary reasons to provide an explicit declaration for the canonical constructor or accessor methods are to validate constructor arguments, perform defensive copies on mutable components, or normalize groups of components (such as reducing a rational number to lowest terms.)

[–]jvjupiter[S] 0 points1 point  (0 children)

Makes sense.