News for hackers. Stuff that matters.
Re:JVM/Java: Null-Restricted and Nullable Types by jeroenhd on Friday August 02, 2024 @05:33AM (#41137336)
The difference between this approach and the approach C# took when they implemented this a few years ago is intereting. With C#, you enable nullability in a project, and every variable is declared as non-null unless you explicitly mark it as nullable (or use compiler directives to disable nullability for a block of code). With this proposal, all existing variables will be effectively nullable, explicitly nullable, or explicitly non-nullable.

Kotlin, another JVM language like Java, also follows the C# approach, assuming everything is non-null unless explicitly marked as being non-null, except Kotlin doesn't have backwards compatibility to worry about. Kotlin also offers a special `lateinit var` declaration for leaving a non-nullable type unassigned until initialization in another method, throwing a special exception on uninitialized access, which is an interesting workaround for some code patterns that this approach doesn't seem to cover.

I wonder why the choice to offer three options was made. Why not keep the non-annotated variables as nullable and make annotated variables explicitly non-null instead? I can't think of a reason why you would want to declare something as nullable when not declaring anything automatically makes the type nullable anyway.

I think I like C#'s approach better, although this has the benefit of being usable in a legacy code base without having to solve any of the nullability issues. Then again, the C# approach does immediately highlight nullability issues in a code base, whereas this proposal hides them the same way they've always been hidden.

Additionally, I find this strange:

> One method may override another even if the nullness of their parameters and returns do not match.

This feels like a footgun for when a developer overrides/implements some kind of callback and returns null where the overridden method specifies non-null return values.

Re:JVM/Java: Null-Restricted and Nullable Types by ygra on Friday August 02, 2024 @06:28AM (#41137591)
I'm currently involved at work with migrating a legacy C# code base to nullable reference types. One thing I'd really like is the explicit marker for non-nullable since it makes it explicit which parts of the code have already been looked at and annotated. For time reasons we've opted to just enable the annotations for now except in a few core places. But we still retain the JetBrains NotNullAttribute and CanBeNullAttribute as markers for now to immediately see where we've made a conscious decision (granted, the latter can be removed since nullable has an explicit marker, but the former has a name conflict with C#'s own feature).

So in that sense having the three options would be quite desirable. Especially since a few hundred thousand lines of code aren't that quick or easy to migrate.

In another internal project we've been doing this in a different way by sprinkling #nullable enable around the code where we touch it and thus gradually improve nullability coverage (and keep in mind that new code must be in a nullable context). This works as well to make it explicit what is annotated already, but it's a much smaller codebase and team.

Re:JVM/Java: Null-Restricted and Nullable Types by Deukhoofd on Friday August 02, 2024 @10:18AM (#41138999)
What we did was to turn on nullability as warnings everywhere. We then went through them project by project, and fixed them. After we were done with a project, we'd turn on WarningsAsErrors for nullable warnings, and know the project didn't need additional fixes any more.
Re:JVM/Java: Null-Restricted and Nullable Types by ygra on Friday August 02, 2024 @03:06PM (#41141639)
Would have loved to do the same and that's my plan eventually, too. Alas, no time for fixing right now. And as I've already noticed when migrating from JS to TS or non-strict TS to strict TS, there's a whole lot of issues that require thought and investigation whether everything is fine from a nullable perspective. I have found quite a few issues, even outright bugs, but when there are more pressing issues than a few lingering NullReferenceExceptions that no customer has stumbled over in the past decade, then those get prioritized.

At least new code is forced to deal with those warnings for now, which is much easier than fixing legacy code.

Re:JVM/Java: Null-Restricted and Nullable Types by layer8 on Friday August 02, 2024 @07:53AM (#41138076)
I agree that it is strange. What I would have expected is that (a) T? means nullable (the existing semantics) and T! means non-nullable, and that the default for plain T can be specified using a pragma-like declaration per source file (and/or per package file), and (b) the following LTS Java release would switch the global default. This would allow easy switching of projects (you can insert/update the pragma in an automated fashion), and also allow keeping the old default when needed.

In addition, the existing @Nonnull annotation could have been leveraged as being the way how nonnullable type occurrences are indicated in class files, providing two-way compatibility for old JDKs.

Re:JVM/Java: Null-Restricted and Nullable Types by twic on Friday August 02, 2024 @12:09PM (#41140022)
Sounds pretty good. But i think the mode selector has to be in the source code where a reader can see it, which rules out a compiler switch.

The current proposal doesn't exclude this possibility in the future, does it. Maybe one day you will be able to declare a class

  public class! MyClass {
or have a package-info file which says

  package! com.initech.accounting;
Re:JVM/Java: Null-Restricted and Nullable Types by layer8 on Friday August 02, 2024 @12:15PM (#41140083)
The compiler switch would be for emulating (or for disabling) the global switchover that we want to take place at some point. We currently have the wrong default, so to speak, and we’d want to change that at some point. Then it is useful to already be able to do that in earlier releases, and also to be able to revert to the old default in later releases.

Otherwise, I agree that it should be in the source. In practice, looking for the presence or absence for T? vs. T! will be a good heuristic for whether the code assumes the new or the old semantics.

Re:JVM/Java: Null-Restricted and Nullable Types by emccue on Saturday August 03, 2024 @03:30PM (#41148672)
To use the terminology from JSpecify:

    null-marked module accounting {
    
    }

Could very well be the sort of thing that comes next.
Re:JVM/Java: Null-Restricted and Nullable Types by jiehong on Friday August 02, 2024 @05:57AM (#41137451)
At the end, there is this section:

> Providing a mechanism in the language to assert that all types in a certain context are implicitly null-restricted, without requiring the programmer to use explicit ! symbols.

Could be nice, even if just as a compiler flag or a module tag.

Re:JVM/Java: Null-Restricted and Nullable Types by dmichulke on Friday August 02, 2024 @05:39AM (#41137360)
I suppose the reason is backwards compatibility of code, something that Java values a lot more than other languages.

Still, I also suppose there's going to be a compiler flag that auto-assumes non-nullability unless specified otherwise.

Re:JVM/Java: Null-Restricted and Nullable Types by jeroenhd on Friday August 02, 2024 @06:31AM (#41137615)
On the one hand Java is very strict about backwards compatibility (still reserving keywords like const and goto even though they're not used (anymore)), but on the other hand Java 9's module system broke just about every Java <=8 project I've ever seen.

Project Loom also breaks tons of code because of locking and other threaded side effects that weren't even a consideration before, a trade-off between coloured functions and risking old code breaking.

It seems to me that Java is very conservative when it comes to the language itself, but actually compiling and running that language seems less of a concern. In this case, the "specify a flag to make all non-annotated variables non-null" approach would only add a single glyph to the language (the ? for denoting nullability), which I would've expected based on the way Java has evolved over time.

Re:JVM/Java: Null-Restricted and Nullable Types by deely3 on Friday August 02, 2024 @07:43AM (#41138012)
> Java 9's module system broke just about every Java <=8 project I've ever seen.

As far as I understand, some IDE's and built automation tools did not rollout support for module system immediately, yes?

Re:JVM/Java: Null-Restricted and Nullable Types by mschuster91 on Friday August 02, 2024 @08:34AM (#41138328)
Mixing a Java >= 9 project with Maven libraries made for <= 8 is one hell of a headache.
Re:JVM/Java: Null-Restricted and Nullable Types by jeroenhd on Friday August 02, 2024 @10:55AM (#41139280)
It took a while for IDEs and tools to catch up, but I still encounter issues with old codebases to this day, using the latest and greatest tools.

The problem isn't necessarily that the compiler isn't called right, but rather that a lot of existing library code suddenly didn't work anymore. By compartmentalising code (a welcome improvement!), projects that weren't designed for this compartmentalisation need a lot of "basically turn off Java module restrictions" command line flags to the JVM.

Re:JVM/Java: Null-Restricted and Nullable Types by kaba0 on Friday August 02, 2024 @08:33AM (#41138322)
> but on the other hand Java 9's module system broke just about every Java <=8 project I've ever seen

That’s not true at all. Besides the package name change with jakarta, all it did is just expose a couple, popular libraries that were depending on runtime internals. Most of this could be fixed by bumping said libraries version. And the whole point of the module system is that it will never happen again, due to stricter encapsulation.

> Project Loom

How would it break any code? You have to explicitly use virtual threads, normal threads are not touched at all and will work as they have always did.

And yeah, java has always been “conservative on the language front, state-of-the-art on the runtime”

Re:JVM/Java: Null-Restricted and Nullable Types by whartung on Friday August 02, 2024 @10:10AM (#41138931)
JDK 9 was the impetus, but the real nail was, I think, 17 when a lot of the constraints imposed by the module system became required. Before that folks could pretty much continue as usual with little regard to the module system.

After 17, legacy systems needed to start adding runtime options to work correctly. And, as I recall, this was mostly constrained to the dynamic, reflective, and introspective properties. Generic jars and code can still run without the module system.

Unfortunately, a lot of the magic in modern Java is through those reflection aspects. So it made moving to 17+ an effort for many legacy code bases.

And it should be clear, in general, all of the code was fine. It was all runtime options setting up package permissions that was the problem. Doesn’t make it less frustrating.

(And I’m pretty sure 17 was the rubicon for this, but it may have been another version.)

Re:JVM/Java: Null-Restricted and Nullable Types by thayne on Friday August 02, 2024 @10:56AM (#41139289)
> That’s not true at all. Besides the package name change with jakarta, all it did is just expose a couple, popular libraries that were depending on runtime internals. Most of this could be fixed by bumping said libraries version.

I don't remember the exact details, but I worked on a project that was stuck on java 8 for a long time because some critical dependencies broke in java 9, and it took a long time before they released versions that were compatible with java 9.

Re:JVM/Java: Null-Restricted and Nullable Types by cesarb on Friday August 02, 2024 @09:46AM (#41138770)
> How would it break any code? You have to explicitly use virtual threads, normal threads are not touched at all and will work as they have always did.

You often have no control over what kind of thread the caller of your code is using. Code written for the old threading model can and will end up being called by these newfangled virtual threads. If it does something the virtual threads don't like (which, as far as I have heard, includes things like some uses of synchronized blocks), you can have unexpected breakage.

Re:JVM/Java: Null-Restricted and Nullable Types by imtringued on Friday August 02, 2024 @10:05AM (#41138881)
You're confusing the thread pinning problem with "breakage". The problem with some synchronized blocks is that they lead to thread pinning for the duration of the lock. Why is thread pinning bad? Because it means that if one core is idle, but all the threads are pinned to a specific core, you won't get full CPU utilisation. This undermines the performance benefit of virtual threads, because they are supposed to be schedulable via work stealing.
Re:JVM/Java: Null-Restricted and Nullable Types by kaba0 on Friday August 02, 2024 @09:56AM (#41138834)
That’s not backwards compatibility, but forwards compatibility, though. And you would really have to go out of your way to introduce such an issue. Certain extreme (e.g. native calls) cases are handled by simply pinning a virtual thread to a real thread. So it would only cause an issue if it was already causing an issue at much smaller thread numbers.

And many of these extreme cases are getting “solved” to not pin the thread.

Re:JVM/Java: Null-Restricted and Nullable Types by Tainnor on Friday August 02, 2024 @10:43AM (#41139174)
Another problem with (especially older versions of) Java is that the language was so restrictive that many of the popular frameworks rely on reflection and/or bytecode manipulation and these things can and do break frequently across JDK or JRE updates.
Re:JVM/Java: Null-Restricted and Nullable Types by pjmlp on Friday August 02, 2024 @07:42AM (#41137996)
As someone that works across JVM, CLR and Web ecoystems, dealing with C# approach is still a mess, unless one is lucky enough to only work in greefield projects.

It is made worse, by being a C# 8 feature and not usable in libraries that need to stay compatible with .NET Framework (yep still plenty of stuff going on there).

Re:JVM/Java: Null-Restricted and Nullable Types by ygra on Friday August 02, 2024 @07:51AM (#41138068)
AFAIK you can still use it for older frameworks. The compiler embeds the attributes into the assembly when they're known to not be part of the runtime library [−3.7]. You can do the same with the various conditional nullability attributes.

[−3.7]: https://sharplab.io/#v2:EYLgHgbALAPgAgZgARwExIMJIN4FgBQSRKyc...

Re:JVM/Java: Null-Restricted and Nullable Types by pjmlp on Friday August 02, 2024 @08:53AM (#41138458)
Yeah, those are the kind of tricks I don't like playing, because when things break down, someone has to sort out the mess.
Re:JVM/Java: Null-Restricted and Nullable Types by jacobparker on Friday August 02, 2024 @11:51AM (#41139877)
The one nullable gotcha with doing this is that the .NET standard library doesn't have nullable annotations in older frameworks.

One approach to adding nullable annotations to a large code-base is to go "bottom-up" on DLL at a time. The annotations are somewhat viral; if you were to go top-down then as you get to more of the "shared" DLLs and add annotations you'll find yourself having to go back and revisit the DLLs you already migrated. In this light, the .NET standard library situation is problematic.

Imagine implementing IEnumerable<T> by wrapping another IEnumerable<T>; in .NET framework there are no nullable annotations, so you can get into a situation where you don't add a nullable annotation where you will eventually need one upgrading to newer .NET. This can bubble up throughout your code base, making that eventual .NET upgrade more challenging.

I'm not saying its not worth it to do this in .NET framework, but you can very easily add extra work to the inevitable(?) update to .NET 8+. When you get there you could of course temporarily regress and turn nullable stuff back to warnings until you work through that surprise backlog, but nullable is really nice so you might be strongly inclined to not do that... not a huge problem, just something to be aware of!

Re:JVM/Java: Null-Restricted and Nullable Types by ygra on Friday August 02, 2024 @03:03PM (#41141615)
Yeah, I've been through that recently as well. The fix for now was to temporarily switch to .NET 8, apply a code fix that adds the inherited nullable annotations throughout the whole solution and revert back to .NET Framework 4.8.

This shouldn't be a problem when multi-targeting, but we've opted to not use that for now for other reasons (performance in Rider, mostly).

Re:JVM/Java: Null-Restricted and Nullable Types by QVVRP4nYz on Friday August 02, 2024 @05:46AM (#41137407)
> I can't think of a reason why you would want to declare something as nullable when not declaring anything automatically makes the type nullable anyway.

All existing code is "we don't know if it is nullable until someone reviews it", that is different than explicitly allowing nulls. To add to confusion all Optional<> variables should be not-null or using Optional makes no sense at all.

Re:JVM/Java: Null-Restricted and Nullable Types by jeroenhd on Friday August 02, 2024 @06:09AM (#41137505)
Optional<> is such a weird addition to the language. I hope once this link lands, Optional<> will go the way of the dinosaur.

I use Optional<> but only to indicate at the API level that something can return null. I hope the chaining ability (?. in many languages, implemented as Optional.map()) will also one day make it to Java.

Re:JVM/Java: Null-Restricted and Nullable Types by neandrake on Friday August 02, 2024 @06:52AM (#41137728)
I don’t even prefer it for indicating that something can return null. In most cases the Option API is more tedious and awkward than a null check and there are existing annotations that can be used to flag nullable return types, for documentation. The only places I’ve found Option to be helpful are where it helps with method composability, or in some hashmaps as a simple way to distinguish between “lookup not previously tried” vs “lookup resulted in no value” vs “lookup resulted in value” - it’s a hack and looked down upon because the Option value itself is null, but I view it the same as “Boolean” being nullable. As long as the details are encapsulated it’s not too problematic.
Re:JVM/Java: Null-Restricted and Nullable Types by joncrocks on Friday August 02, 2024 @06:41AM (#41137657)
Indeed, Optional<> was designed/intended to be used in this way.

https://stackoverflow.com/questions/26327957/should-java-8-g...

Re:JVM/Java: Null-Restricted and Nullable Types by unscaled on Friday August 02, 2024 @08:41AM (#41138372)
Unfortunately for Java, Optional in Java is a bit of mess now, until you'll be able to specify nullability. Since T in Optional<T> has unspecified nullability, calling Optional.of() is still unsafe and can result in an NPE, if the argument is null.

What's even worse is that APIs that return Optional<T> can just return null for the Optional value itself! This a pretty evil thing to do on purpose, but this could still easily happen by mistake. If you want to make code using optionals null-safe you have to go through quite some hoops and check that both that Optional<T> is neither null nor empty.

I hope Java can now change the API of Optional and make it safer. For instance, Optional<T>.of() should require a `T!` argument, while Optional.flatMap() should require that the mapper returns a non-nullable Optional value. Likewise, linters should reject any definition of an Optional that is nullable or has unspecified nullability.

Re:JVM/Java: Null-Restricted and Nullable Types by oftenwrong on Friday August 02, 2024 @09:12AM (#41138594)
>but this could still easily happen by mistake.

I have yet to see this ever happen, despite working in Java shops using Optional heavily since it was included in the JDK. I would guess that this is due to developers using better tooling. IDEs commonly provide warnings when returning null, or when violating a "soft" nullability assertion marked by an annotation. NullPointerExceptions seem fairly rare.

Re:JVM/Java: Null-Restricted and Nullable Types by unscaled on Friday August 02, 2024 @10:59AM (#41139323)
I do remember seeing this happen firsthand, but I don't remember where.

Yes, this is not likely to happen with a good IDE with warnings enabled, and developers not ignoring said warnings. It is even less likely with a strict lint step in your CI/CD which treats all non-suppressed warnings as errors. This should be the standard for every software project in the world.

Unfortunately, for many enterprise scenarios, developers are not encouraged (or even discouraged) to apply these best practices. I'm talking about your typical setting with non-technical management, low-salaried or outsourced developers, tech debt rarely being fixed and the only best practices which exist date back to the 1990s or early 2000s.

Doubly unfortunate is the fact that shops of this type _overwhelmingly_ favor Java. For better or worse, Java is the #1 enterprise language and the COBOL of the 21st century. As such, something that would be a non-issue in Rust (where few developers would dare push to production code that didn't pass cargo clippy with flying colors), becomes a rather big issue in many shops.

Re:JVM/Java: Null-Restricted and Nullable Types by jonathanlydall on Friday August 02, 2024 @12:07PM (#41140000)
While applying practices like treating warnings as errors on a CI server is something that every development team probably should be doing, it’s more a symptom of a generally weak development team than the thing that was holding the team back.

If a company policy mandated that it must be on, it would probably not meaningfully reduce poor code because the team was so poor in the first place, they probably don’t understand the problem it solves, so will just work around the now “error” using the least amount of effort to appease the CI server, while still leaving problems in their wake.

Strong teams regularly and consistently reflect on their processes towards continuously improving, such teams will naturally move to applying such a practice as it will add value.

Weak teams tend to just do what they always did until forced to do something new and even then they do it more cargo cult style than in a way that actually improves the bottom line.

Re:JVM/Java: Null-Restricted and Nullable Types by pjmlp on Friday August 02, 2024 @09:08AM (#41138564)
All the value like types, like Optional, are planned to be value classes or value records, when Valhala lands.
Re:JVM/Java: Null-Restricted and Nullable Types by usrusr on Friday August 02, 2024 @10:31AM (#41139070)
I use Optional quite a lot, but only ever as a poor man's

   x?.let{f(it.y)}
via

   Optional.ofNullable(x).map(it->f(it.y)).orElse(null);
Will it at least get taken care of by escape analysis?

These days I'd not even trade the simple but effective approach taken by Kotlin for the full glory of Scala's Option (which is so far beyond the Java Optional).

Re:JVM/Java: Null-Restricted and Nullable Types by marcosdumay on Friday August 02, 2024 @12:20PM (#41140139)
Optional<> is a problem with all languages that add nulability control as an afterthought.

If I have v = Optional<A>, if v.hasValue() does it mean v.value is not null? How does it interact with the nullability control? If v? has type Optional<A>, how do I write Optional<Optional<A>>? (And if you think that type doesn't make sense, you haven't really internalized the "parse, don't verify" rule.) If v? doesn't have type Optional<A>, why the fuck both types exist and when should I use each?

Re:JVM/Java: Null-Restricted and Nullable Types by BoardsOfCanada on Friday August 02, 2024 @06:44AM (#41137674)
My experience with kotlin and c# is that in kotlin it just works, even with java interop, while in c# nullable value types seem like a far leakier abstraction.
Re:JVM/Java: Null-Restricted and Nullable Types by aardvark179 on Friday August 02, 2024 @05:52AM (#41137434)
I think this is all a compromise to allow the introduction of this gradually in a code base and across the standard library. You want to start marking these intentions in interfaces and base classes, but you don't want to immediately invalidate all existing implementations.
Re:JVM/Java: Null-Restricted and Nullable Types by afiori on Friday August 02, 2024 @05:37AM (#41137353)
> I can't think of a reason why you would want to declare something as nullable when not declaring anything automatically makes the type nullable anyway.

It can more clearly show intent. Is is similar to the argument for using const in javascript: you should use const as much as possible so that when you see a let you know that it is going to be mutated at some point.

Re:JVM/Java: Null-Restricted and Nullable Types by the_gipsy on Friday August 02, 2024 @06:47AM (#41137689)
This way Java can claim that it has this feature when comparing to competing languages, without interfering with all the legacy code. It doesn't matter if it's not useful, some manager can just run down a checklist and pick safe ol' Java.
Re:JVM/Java: Null-Restricted and Nullable Types by unscaled on Friday August 02, 2024 @08:26AM (#41138273)
Kotlin does have types with unspecified nullability, although you cannot define it directly. Kotlin calls them "platform types"[1], and they're annotated with an exclamation mark (e.g. "String!" for a possibly-nullable string) in errors and diagnostics.

Both the term "platform types" and the exclamation mark symbol are confusing, but other than that Kotlin's approach works quite well. Since Kotlin has nullability from the very beginning, the programmer can't specify platform types directly, but Kotlin still needs to support them to maintain compatibility with underlying platforms that support unspecified nullability, such as the JVM and JavaScript.

With this approach, the defaults are still sane[2] (always non-nullable by default — everybody who thinks otherwise has learned nothing from Tony Hoare[2]), but the backward compatibility is maintained. But Kotlin got it easy, Java and C# also need to maintain compatibility with existing source code.

Neither Java's approach or C#'s approach seems ideal. The C# approach drastically changes the behavior of the code based on a compiler flag, while the Java approach makes the default into the worst possible choice.

I still lean towards the C# solution, because I think making "maybe-nullable" the easiest choice, means most programmers will choose it by default. Especially in an enterprise-friendly language like Java. Linters and compiler warnings would help in the long-term, but I think it will be many years before most of the Java code will be properly annotated for nullability. C# users will see more pain in the short term, but they will probably get to the promised land of clear nullability much faster.

[1] https://kotlinlang.org/docs/java-interop.html#null-safety-an...

[2] https://www.infoq.com/presentations/Null-References-The-Bill...

Re:JVM/Java: Null-Restricted and Nullable Types by simon_void on Friday August 02, 2024 @11:51AM (#41139878)
you failed to mention that Kotlin has platform types only if it's interoperates with Java. Platform types are for objects that come over from Java code (and therefore have unspecified nullability (assuming the Java code doesn't use nullability annotations)). Admittedly you provided a link that explains this, but how many people will follow the link? And yes, this detail feels kind of important. And yes, future Java (and Kotlin) will only have their version of platform types to interop with old Java code.

As a long-time Kotlin user I can only say: Nullability is nice! Once you know it, you won't want to code without it.

Re:JVM/Java: Null-Restricted and Nullable Types by unscaled on Friday August 02, 2024 @12:13PM (#41140066)
I did mention all of this:

"[...] but Kotlin still needs to support [platform types] to maintain compatibility with underlying platforms that support unspecified nullability, such as the JVM and JavaScript."

To be more accurate, "platform types" are not used with JavaScript, but you do get something similar in that case. I haven't worked with Kotlin/JS at all, but from my understanding if you do not have proper type definitions, you have to deal with dynamic types - which are also nullable.

Re:JVM/Java: Null-Restricted and Nullable Types by mmis1000 on Friday August 02, 2024 @12:06PM (#41139994)
The type kotlin generated from java code also inserts nullable specifier if java code have @NonNull or @Nullable specified.

When kotlin see these exist. It will convert the type to null enforced type instead. Which give you a tool to gradually convert you project to null enforced type if you can't convert it to kotlin at once.

Re:JVM/Java: Null-Restricted and Nullable Types by UncleMeat on Friday August 02, 2024 @08:55AM (#41138480)
Its a footgun, but one chosen for practicality. There have been a number of other nullability annotation frameworks for java in the past that are more complete and correct, but also more difficult to use and understand for a typical developer. A classic example is "what about nullness of fields defined in constructors?" After all, there is a real moment in program execution where those fields store nulls. So people try to add things to represent "nullable, but once non-null it remains non-null forever" or whatever and then people don't practically use the system because it is too much conceptual complexity.
Re:JVM/Java: Null-Restricted and Nullable Types by lolinder on Friday August 02, 2024 @09:06AM (#41138551)
Another practical answer is to just accept that an edge case like that is one we won't completely solve for.

Kotlin will yell at you if you don't initialize everything in the constructor and will yell at you if you try to use a variable in the constructor before it's declared, but if you call out to another function in the constructor you're on your own and might end up with nulls.

That's not complicated to understand, but it eliminates most types of not-yet-initialized nulls in the language.

Also, isn't how you handle not-null types in constructors totally orthogonal to which syntax is used for not-null and whether there's a third I-dunno-if-null type? And is a three-way nullability system really simpler to understand?

Re:JVM/Java: Null-Restricted and Nullable Types by foolfoolz on Friday August 02, 2024 @10:02AM (#41138874)
how does the project level null flag work for libraries?

lets say a library was written with no nullability flag selected (legacy jar). i import that jar into my code. in my code i enable all variables as non-null by default

Re:JVM/Java: Null-Restricted and Nullable Types by gwbas1c on Friday August 02, 2024 @12:25PM (#41140183)
> This feels like a footgun for when a developer overrides/implements some kind of callback and returns null where the overridden method specifies non-null return values.

I've caught "null!" in C# code reviews a few times: My response is usually "You can't fix your code by yelling at it."

The reality is that C#'s approach also has some nasty footguns that require understanding the nuances of the "required" keyword, and when values are assigned.

Re:JVM/Java: Null-Restricted and Nullable Types by eru on Saturday August 10, 2024 @09:29PM (#41213389)
> I can't think of a reason why you would want to declare something as nullable when not declaring anything automatically makes the type nullable anyway.

To show the reader of your code that you explicitly want this nullable, instead of just being too lazy to type?

You can then use a linter to forbid the implicit behaviour in your code.