u/Fenrurrr

▲ 58 r/java

Why not a language-level "null-marked" directive at the file/package scope in Valhalla, instead of annotating every type with ! ?

I've been reading up on Project Valhalla and the null-restricted types work. As I understand it, the proposed syntax is:

Point! p;   // cannot be null
Point? p;   // explicitly nullable
Point  p;   // unspecified (legacy default)

My question: instead of forcing me to sprinkle ! on basically every field and parameter, why couldn't we declare a directive at the top of a file (or package) that flips the default? Something conceptually like:

// hypothetical: this whole file is non-null by default
non-null;

class Cursor {
    Point position;    // implicitly non-null
    Point? lastHover;  // opt back IN to nullable with ?
}

So:

  • With the directive → everything is ! by default, and you write ? for the rare nullable cases.
  • Without the directive → you keep today's behavior and write ! explicitly when you want non-null.

In most codebases non-null is overwhelmingly the common case, so this would massively cut the noise. More broadly, I'd love to see Java adopt the modern-language mindset here: non-null by default, with nullable being the explicit exception you opt into (the way Kotlin, Swift, Rust… do it). That feels like the healthy direction for the language.

And I get that this is exactly where the hard part is: backward compatibility. That's precisely why I'm proposing an opt-in directive at the file/package level rather than changing the language's global default. If Java suddenly decided that a bare Point means "non-null," that would be a semantic change across billions of existing lines — code that compiles and runs today could start breaking. That's the very reason the current proposal keeps bare Foo as "unspecified": to not break existing code. An explicit directive, on the other hand, would only apply to the files/packages that declare it — so zero impact on old code, and gradual file-by-file migration. This is basically the spirit of JSpecify's @NullMarked (set at the package level via package-info.java), except it'd be carried by the language and compiler rather than a third-party annotation.

For what it's worth, the Valhalla team has explicitly said a class/module-wide marker "may be added later" but it isn't in the current draft — for now each type use is annotated individually.

So my actual questions for the sub:

  1. Has this idea — a language-level "non-null by default" scope (file/package/module) — already been formally proposed (a JEP, the valhalla-spec mailing list…)? If so, what was the sticking point?
  2. Since it'd be opt-in, is backward compatibility really a blocker here, or are there subtleties I'm missing (e.g. interactions with inheritance, generics, nested types)?
  3. Would mixing a file-level default with explicit !/? hurt readability ("is this Point non-null because of the directive, or because I forgot?")?
  4. Are people already treating @NullMarked + JSpecify as the de-facto answer until the language catches up?

Curious how others see the tradeoff between "explicit everywhere" vs "sane default + opt-out."

reddit.com
u/Fenrurrr — 17 days ago