<div dir="ltr">Hey everyone,<div><br></div><div>Most language changes affect only implementation code, but a few like record classes and now value classes are API-affecting: they permit new API shapes to be expressed, and thereby new ways for a client class to depend on a library class.</div><div><br></div><div>These features are very carefully made backward-compatible, but there's a sort of second-level backward compatibility as well: can a library owner fully exploit the feature in a way that is *itself* backward-compatible for its clients? Looking at things this way brings in a whole host of new issues (since libraries often get stuck on old versions and often get run on a wide range of Java versions newer than the one they built and tested on, among other reasons).</div><div><br></div><div>Record classes seem to come out well in this regard. From what I can tell, there should be many "record-like" classes today that can smoothly become records that all clients will still compile against and work with. Some `getFoo()` methods might have to be preserved as pass-throughs to `foo()` and maybe some details like that, but it looks pretty clean to me (?).</div><div><br></div><div>But migrating to a value class is rescinding functionality and so inherently *not* backward-compatible. So, libraries can only do it via a multi-step process, over time. This thread is happening because I think this project probably wants to support that process, but I'm not clear yet on how it would do so.</div><div><br></div><div>If we did nothing else, we'd be counting on something like <a href="https://github.com/jspecify/jspecify/issues/488">this JSpecify feature request</a> to happen (please skim that, it helps explain what I'm even talking about in this thread). If we feel fine about hoping for the best on that front, then you can skip the rest of this message (I'd shift my argument to petitioning Oracle to support that effort!). That is, the remainder is motivated by the assumption that Java itself wants to actively support these migrations.</div><div><br></div><div>Anyway: it looks very compelling to me to put that `@ValueClass` annotation, such as described, into Java itself, and have javac support it in the very same way it's going to support value class validation. (Even, of course, applying it to Integer and friends.)</div><div><br></div><div>I'd even ask whether we could take it a step further. Once Java introduces the `value` keyword, there is <i>still</i> a lot of value (ugh) in having the annotation, and having it mean *exactly* the same thing, with all the same effects. This has a feeling of heresy to it, but it does something pretty powerful I think: it allows library owners to write <i>forward</i>-compatible code, that does the right thing whether its clients are using Java N-1 or Java N. Which makes the event of its users upgrading to Java N ... a little closer to a <i>non-</i>event.</div><div><br></div><div>I suspect this of being reasonable. Since that Java N-1 client won't be able to use `non-atomic` or `!` or `?` or whatever we're calling the kind of constructor that makes the class a "never-null" type, I think the Java N-1 VM is within its rights to do almost nothing about the `value` keyword. (Perhaps prevent synchronization, and let's stick a pin in a discussion about equality semantics for the moment.) Which is good because it wouldn't know <i>how</i> to do those things.</div><div><br></div><div>In fact, the earlier a version of Java we could backport this annotation and its javac support to, the better, AFAICT. With each version earlier we could push it, that much more code gets to become safely forward-compatible today.</div><div><br></div><div>This is a much longer discussion but let me cut this message off here as a conversation-starter. Please start poking holes!</div><div><br></div></div>