<div dir="ltr"><div><font size="4">Hi Guys!</font></div><div><br></div><div><span style="font-family:monospace;font-size:large">So, we get that adding null restriction to Java will significantly worsen the fact that "nullable" is yet another bad default; this is pretty clear.</span></div><div><span style="font-family:monospace;font-size:large"><br></span></div><div><div><br class="gmail-Apple-interchange-newline"><font size="4">About "nullable" being a bad default. Have you thought for value classes the default to be not nullable?</font></div><div><font size="4"><br></font></div><div><font size="4">Like the == comparison that is being "fixed" where value objects compare if they are of the same class and have the same field values.<br><br>If we think in the long future to "fix" the default to be not nullable, this would be a step.<br><br>Thinking about reading code, maybe it is not a good choice to have this difference between value and identity objects because we would have to check the variable type to understand the logic.<br><br>Obviously not for the first versions!</font></div><div><font size="4"><br></font></div><div><font size="4">Thanks!</font></div><div><font size="4">Anderson.</font></div><div><br></div></div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Nov 15, 2024 at 1:55 PM Brian Goetz <<a href="mailto:brian.goetz@oracle.com">brian.goetz@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><u></u>
<div>
<font face="monospace" size="4">
<blockquote type="cite">
<pre>Before anything makes it into the JDK I'd like to see the plan for
this</pre>
</blockquote>
<br>
This is a valid opinion, but let's be clear what you're saying: it
means you think that having a solid, committed flippening story is
so important that you're willing to say that "no one can have the
benefits of valhalla for another 5-10 years, or maybe ever."
That's a pretty big deal. (And, yes, sometimes we are willing to
make such tradeoffs, but it's still a pretty big deal.)<br>
<br>
But, maybe that's not what you meant. Maybe what you meant is "I
want to impress on you how important I think it is to get to where
the nullity default is flipped." If that's what you mean, yes, we
understand how strongly some people feel about this. Our
antipathy to attacking this problem *right now* is not because we
don't think it is a real pain point, but one of practicality: it's
not possible to solve all the problems simultaneously and still
deliver something in a mortal lifetime. <br>
<br>
Or maybe what you meant is "there seem to be simple solutions to
this problem, why wouldn't we jump on them?" Unfortunately just
because a solution is obvious (like "let's just put a bang on the
module directive"), doesn't mean they are simple. </font><font face="monospace" size="4">(To be clear, you are asking for what
would be, by far,
the biggest change to Java ever -- reinterpreting existing code to
mean something else based on a directive _in another file_.) Rest
assured that we've seen these "solutions" proposed before, and our
lack of enthusiasm for them is that they may well create more
problems than they solve.<br>
<br>
So, we get that adding null restriction to Java will significantly
worsen the fact that "nullable" is yet another bad default; this
is pretty clear. But if we really thought that we can't do
Valhalla until we reinterpret all the world's Java code with a new
default, the rational response might well be to cancel the
project. Sometimes things have to be separated out into smaller,
dependent chunks; sometimes we even have to accept that we might
not even get to all the later chunks. <br>
<br>
I get that you would be more comfortable if we had a committed,
bulletproof plan for this. But I think I can say with confidence
that we won't; we need to focus our attention on the many
nearly-impossible problems we already have in front of us before
adding more to our plate.<br>
<br>
<br>
</font><br>
<br>
<div>On 11/15/2024 11:16 AM, Caleb Cushing
wrote:<br>
</div>
<blockquote type="cite">
<blockquote type="cite">
<pre>It is not a goal to automatically re-interpret existing code—use of these features should be optional and explicitly opted in to (future work will explore mechanisms to request a bulk opt-in without needing to change individual types)
</pre>
</blockquote>
<pre>Before anything makes it into the JDK I'd like to see the plan for
this, especially since I do not believe such a feature should be
released unless it has been applied to the entirety of the JDK.
Without this the adoption will be almost as slow as JPMS (an aside on
that I'd like progressive enforcement there so it could be possible to
get there).
Not to speak for anyone other than myself, the community seems to be
leaning towards the conversion where non null is the default, and
using marker annotations on packages,classes,modules. This or
something like this to speed conversion would be appreciated. maybe
the following (Evil tangent: let this only exist on module, I'd like
to get modules actually moving, in a different email it'd be nice if
jars without at least an automatic module would start failing to load)
module org.example! {} // or ?
package org.example.something!; // or ?
could be used for speedy defaults on otherwise unmarked code. Some
have taken to separating API and Fields though.
How do these behave? given the following interface, static
implementations (meaning they aren't doing real loads from an external
database), that Stream::map arguments are marked "?" as nullable and
use
interface MyRepository {
Stream<Foo?>! findFoos();
}
class Foo {}
given
class MyRepositoryValueNeedsNullCheck implements MyRepository {
Stream<Foo?>! findFoos() {
return Stream.of(new Foo(), null);
}
}
class MyRepositoryValueDoesNotNeedNullCheck implements MyRepository {
Stream<Foo?>! findFoos() {
return Stream.of(new Foo());
}
}
when MyRepositoryValueNeedsNullCheck
findFoos().filter(Objects::nonNull).map( foo -> foo.toString())
when MyRepositoryValueDoesNotNeedNullCheck
findFoos().map( foo -> foo.toString())
will the above be considered "ok" since neither of them would actually
create a runtime error? they should be considered ok in my opinion.
class MyRepositoryValueNeedsNullCheck implements MyRepository {
Stream<Foo?>! findFoos() {
return /// do something with a database or something that
cannot be known until runtime
}
}
when MyRepositoryValueNeedsNullCheck
findFoos().filter(Objects::nonNull).map( foo -> foo.toString())
findFoos().map( foo -> foo.toString())
does the return on findFoos() do an implicit runtime check for the
Stream throwing some good NPE error? will the map without the filter
result in a compile time NPE?
class MyRepositoryValueNeedsNullCheck implements MyRepository {
Stream<Foo!>? findFoos() {
return null;
}
}
is this valid? I have a valid use case for what's more or less the
inverse (where the interface is nullable, but the implementation is
not)
Will we be getting a way to assert variables with inferred types?
`var! foo = null` (tangent: can we reopen mutability on var here?
meaning val! foo or const! foo, that thing I foolishly voted
against... and was wrong, it should exist (I hadn't used a language
that had it yet, maybe I wasn't the only one), I don't like const
because I see that as a static final)
given
Foo! foo;
foo = new Foo();
valid so long as it's assigned before use?
is partial markup really valid at compile time?
interface MyRepository {
Stream<Foo?> findFoos();
}
I find the examples using this, but then Stream is nullable? it feels
like if you define any nullability on a given type then the whole type
should be fully marked up.
In all of these stream examples, the concept in checker framework is
@PolyNull, will there be a way of writing functional interfaces that
defines that the implementers can use them in a PolyNull fashion?
meaning the null check necessity can't be known until usage is
defined?
Will the compiler strip if null checks out of the bytecode if it
determines they are no longer necessary? probably not necessary to
define in the jep.
</pre>
</blockquote>
<br>
</div>
</blockquote></div></div>