<div dir="ltr"><div dir="ltr">Sorry for delay.</div><div dir="ltr"><br></div><div>I've raised a complex topic. Most of what I say in here will need more deep thought and discussion. I don't even have the vocabulary for half of it.</div><div><br></div><div>As a general point: whenever we say "the user can wait for Java N", sometimes that really means "the user can wait until they're ready to de-support Java N-1" which is a lot longer time. And, it's not about "I don't want to wait", but more about "I want to be able to serve the Java N+ users I have right now today and I can't yet".</div><div><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Mar 4, 2024 at 2:26 PM Dan Smith <<a href="mailto:daniel.smith@oracle.com">daniel.smith@oracle.com</a>> wrote:<br></div><div dir="ltr" class="gmail_attr"><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">In the JDK, we are very concerned about compatibility, so we defined "value-based class" to require private (or non-private deprecated) constructors and construction via identity-ambiguous factories. This provides a specified basis for most of the behavioral changes that come with 'value', except for the fail-fast behavior of synchronization.<br></blockquote><div><br></div><div>Ah I forgot to reference that. Yes, I'm talking about making that same concept more official/enforceable. (aside: we can backpedal from the constructor part of it now, right?)</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">1) Things that can be controlled by the class declaration<br>
<br>
There are the basic class structure things (fields, sub- and superclasses). These are pretty self-evident—if you've got a candidate class, you probably already meet these requirements. In anticipation of 'value' coming, maybe you'd like to add some 'final' modifiers in the right place for things that were not explicitly final before.<br>
<br>
Surely if you're prepared to abandon identity, you've already overridden equals/hashCode to support a notion of equality that isn't identity-based. 'toString' probably, too, although I think you can assume your users won't/shouldn't depend on the contents of the random number appearing in the default 'toString' output.<br></blockquote><div><br></div><div>When a user first goes through some classes to decide which to make value classes (whether by keyword or by annotation), I think they're likely enough to uncover various problems they have to resolve. This is who I'm thinking about. I think the sooner they can disavow identity and be prompted to fix up those problems, the better. Partly because the enforcement they'd get is healthy for their codebase *anyway* even if they never upgrade to value classes. And partly it just defrays effort they'd have to do later, and makes the upgrade itself go smoothly. (But these aren't the whole point.)</div><div><br></div><div>Back to the record classes example: if someone can't get on Java 16 yet, I try to <a href="https://twitter.com/kevinb9n/status/1768366963087331713">nudge</a> them to use AutoValue, which even has <a href="https://github.com/google/auto/blob/main/value/userguide/records.md">specific advice</a> to keep your classes forward-compatible with their future recordy selves. These users would basically be "pre-adopting" records, which I think is cool (including in ways I haven't 100% articulated yet).</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Would it be useful to have some tooling that checks all of these things for you? Eh, maybe. I'm not sure there's that much to check—most of it pretty naturally flows from the fact that you're declaring a class that fits in the value-candidate bucket; and making a deliberate choice to avoid identity guarantees via factory-based construction and some extra javadoc is no harder than making a deliberate choice to add a '@ValueBased' annotation.<br></blockquote><div><br></div><div>Perfect, so this is the specific part I'm calling into question. Most code in the world isn't super-well-thought out (and just wait until AI is writing it all haha). The code just happens to seem to work. If a project wants to do better, the only practical ways is with the help of one tool or another. In plenty of cases it's fine to leave that to third-party tools; I'm wondering whether this is one of them or not.</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">2) Corner-case use site failures<br>
<br>
The main purpose of JEP 390 was to more strongly discourage synchronization on types like Integer, because that code will break when Integer becomes a value class. I think that's already a corner case—most people do not write code like this. But java.lang.Integer gets used by everyone, and so an occasionally usage is bound to show up.<br>
<br>
s/Integer/SomeLibraryClass/ and I think we're talking about orders of magnitude fewer use cases.</blockquote><div><br></div><div>I'm more interested in whether it should warn on `==`!</div><div><br></div><div>Yes, I do think (with a very appropriate retcon) that Valhalla's change to it is as compatible as can be (uh ignore float). But, I'm still as concerned about new-`==` as I was a couple years ago. On most should-be-value classes today, `==` is flat-out wrong. Tomorrow, it's just as incorrect -- except it will *happen to work* more often, maybe much more often. I think it will become an "attractive nuisance", and that the sooner we can spur people to stop using `==` on classes that are or intend to become value classes, the better.</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">When we were working out the details of JEP 390, we considered making the @ValueBased annotation public/standard, and decided against it, because we wanted to avoid introducing layers of new concepts for programmers. "How is a value-based class different from a value class?" is not something we want showing up in Java tutorials.<br></blockquote><div><br></div><div>Hmm. I would hope this could be simple. A developer makes the same decision either way, and they just use whichever of `value` or `@ValueBased` is available to them.</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Instead—and I realize this is totally theoretical for me and very practical for you, so I appreciate any hard-earned wisdom you can provide—I'm not that concerned about saying version N of a library migrates some classes to be true value classes, and that should be just fine for most of their users. If somebody has a special issue with synchronization or ==, they should stick with library version N-1 until they can fix it.<br></blockquote><div><br></div><div>I have work to do in explaining what hurts me about this.</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> 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.<br>
<br>
Our normal approach to javac would be to put new warnings in the latest version only. Best we could do is, say, javac 23. And since we expect support for value classes to follow soon after, most of the benefit would be to people who write, e.g., 17- or 21-targeted code, but compile it using the latest JDK.<br></blockquote><div><br></div><div>(Why <i>not</i> do it sooner, particularly if it's a helpful thing anyway?)</div><div><br></div><div>And whenever we talk about something following "soon after", I just think about the fact that the version in between is out there in the world being used *forever*...</div><div><br></div></div></div>