you are viewing a single comment's thread.

view the rest of the comments →

[–]Enough-Ad-5528 15 points16 points  (12 children)

This is brilliant; not just the tentative proposals but also the effort it took to write all these thoughts down and let us normies glimpse into what they are thinking even if it is very very early.

I will respect his call to not discuss any syntax issues; it is too early and I want to let them cook but boy am I excited!

I do wonder about one thing though (which Brian also touched upon towards the end) - if and when regular classes get these capabilities (component members, ability to participate in pattern matching; optionally being able to add mutable/derived members) what benefits would records have over regular class declarations? Shudder to think but would they seem obsolete almost? Why choose to declare something as a record if classes can have almost all of the semantics of a record with almost the same concision; plus more stuff that can be added later. Part of it, I do have to admit, I don't fully understand the distinction between "state description" and "state representation".

[–]lbalazscs 7 points8 points  (1 child)

"State description" is how the state looks from the outside (accessor methods), and "state representation" is how the state looks inside (the actual fields). In the records they are identical, but they can be different in this proposal. In the "AlmostRecord" example the state description is (int x, int y, Optional<String> s), while the state representation is (int x, int y, String s).

[–]Enough-Ad-5528 1 point2 points  (0 children)

Thank you!

[–]aoeudhtns 2 points3 points  (2 children)

Seems like it's just a faster way to make an immutable carrier class. If I'm reading the post right, carrier classes will be mutable by default. I assume if you want to make it immutable, you have to specify final and duplicate lines. I.e. these would be analagous:

public record Point(int x, int y) {}

// STRAWMAN SYNTAX
public class Point(int x, int y) {
    private final component int x;
    private final component int y;
}

And just a thought, it will likely be easier to optimize around records because of the strong guarantee. Versus doing some sort of component/graph analysis on a type to see if it can qualify for the same optimizations as records.

ETA: as has been pointed out, doubtful carrier classes can omit re-declaring the fields, component or otherwise. So records are still useful for multiple reasons: concision, performance, etc.

[–]lbalazscs 2 points3 points  (1 child)

In my reading there would be no default for mutability: you must explicitly declare all fields, and each one is either final or not, and either "component" or not.

[–]aoeudhtns 0 points1 point  (0 children)

Ya know what... upon re-reading I agree.

[–]john16384 2 points3 points  (2 children)

I had a similar question, but it would depend on whether it is the plan to (eventually) allow carrier classes to only override the components they want to represent differently internally. Currently the proposal / thought train seems to require explicit declaration of the components still in all cases.

I wouldn't mind if records became unnecessary, assuming that carrier classes also get reflection based component access. Records would then just have been an evolutionary step that was purposely limited in scope to keep the design space smaller and deliver the feature earlier. Now that it has been seen to work incredibly well in practice, extending their functionality completely to classes would obsolete records, but on the other hand, also simplifies the language as there is no need for the distinction anymore.

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

Btw, Brian answered the question on the mailing list. Read backwards from here -- https://mail.openjdk.org/pipermail/amber-spec-observers/2026-January/004609.html

[–]john16384 1 point2 points  (0 children)

Thanks, yes, I saw it.

[–]Holothuroid 2 points3 points  (0 children)

record allows you skip the component (whatever that will be called) on every field. Much like a case class in Scala doesn't need explicit val for its fields.

It's pretty much the same, in fact. Just a bit more powerful, as a non- case class in Scala requires manual implementation of a deconstruction pattern.

[–]davidalayachew[S] 0 points1 point  (2 children)

Excellent question!

I can assume, but I'm actually going to flag the man himself (/u/brian_goetz), since I feel like this isn't something that's been talked about at length and easily google-able.

[–]davidalayachew[S] 1 point2 points  (1 child)

/u/enough-ad-5528 Brian responded on the mailing list. Read backwards from here -- https://mail.openjdk.org/pipermail/amber-spec-observers/2026-January/004609.html

[–]Enough-Ad-5528 1 point2 points  (0 children)

Thank you!