Null-Restricted and Nullable Types
Antoine Tremblay
marath010 at gmail.com
Thu Nov 13 13:00:16 UTC 2025
I think the ?! syntax is beautiful. We have coded java in an unspecified
null landscape since its inception.
To finally introduce the ability to create specialized value classes, with
a specialized syntax makes a lot of sense.
I don't think the !? syntax would spread like wildfire, I believe it would
stay confined to
-libraries made by makers
-abandoned prototypes by curious developers.
On Thu, Nov 13, 2025 at 6:22 AM ram anvesh reddy <ramanvesh at gmail.com>
wrote:
> Hi Jeremy!
>
> Just so that I understand, couple of questions:
>
> 1. are your saying
>
> Predicate<Optional<Foo>>
>
> is better than
>
> Predicate<Foo?>
>
> 2. How will you represent
> Foo?[]! and Foo?[]?
> Using Optional?
>
> Cheers
>
> On Thu, 13 Nov, 2025, 15:41 Jeremy Lyon, <jeremy.lyon at fastmail.net> wrote:
>
>>
>> *RE: Null-Restricted and Nullable Types*
>>
>> I have been anticipating Valhalla in my work for a while. In doing so I
>> have implemented interfaces that label value objects and nullability. In my
>> code I have 10s of types defined using label interfaces to be both value
>> types and non-nullable types. The idea was that I would anticipate Valhalla
>> and convert the types when Valhalla arrived. I am pleased to say that with
>> the current Valhalla values I am able to convert the relevant types to
>> value classes.
>>
>> I am concerned about nullability, hence this e-mail. Indicating
>> nullability using ! and ? looks like making a big mistake to correct 'the'
>> big mistake of nulls, at least to my eyes.
>>
>> Rather than introduce markers to handle nulls, which seems likely to have
>> the effect of baking-in null handling everywhere, I think it better to
>> eliminate nulls altogether and obviate the need to litter the code with
>> null-handling mechanisms. Better to make the problem go away than to burden
>> the developer with it. (A similar line of thought applies to memory
>> management. Better to have a good garbage collector than burden the
>> developer. [See note 1.])
>>
>> I suggest that it is better to implement some sort of module, package or
>> class modifiers that require code to use Optional instead of null, and
>> eliminating nulls altogether. If code can't generate a null, and can't
>> receive a null, then there will be no nulls, and no need to implement ? and
>> ! everywhere. This makes the most sense if/when Optional itself is a
>> non-nullable value type that is elided from memory wherever it can be and
>> flattened when it can't. And by implementing modifiers that are used as
>> required, programmers who have continuing need of nulls for whatever reason
>> can continue to use it.
>>
>> Java supports Optional today, but it is not 'the standard' for handling
>> null cases. Before Valhalla, I don't think it made sense to make Optional
>> the standard because very Optional is one more memory allocation and one
>> more indirection to have to deal with. Even while the compiler does its
>> best to avoid short lived objects reaching the heap. With Valhalla starting
>> to deliver, it will soon the the case that no significant penalty applies.
>> Adopting Optional as the standard for the null case has years of comp
>> science principles and industry practice behind it showing only good things
>> so I don't think there is any longer much risk in following suit.
>>
>> A decade ago Java modernised to great effect by adopting a form of
>> functional programming. Until then Java was a traditional OOP language. The
>> modern Java style is a mixed style including functional elements that
>> programmers are already familiar with, and that appears to make Java an
>> extremely effective programming language. Optional is already part of Java,
>> programmers are already used to the functional part of Java's mixed style,
>> and Optional fits really well. Stylistically Optional is a no-brainer.
>> Adopting it as the standard for nulls seems likely to me to be a relatively
>> small step for most.
>>
>> In my opinion ! and ? will make Java code more complex to read and write.
>> From "JEP draft: Null-Restricted and Nullable Types (Preview)" (
>> https://openjdk.org/jeps/8303099):
>>
>> Foo?[]!
>> Predicate!<Foo?>
>>
>> I am opposed to this syntax. I don't want to pour over lines of code
>> examining nullness markers to try to figure out what is going on. I think
>> it is obvious that ! and ? burden the developer.
>>
>> Java APIs need to remain compatible with legacy code. Perhaps some sort
>> or auto-(un)boxing (to Optional) can be implemented so that legacy code and
>> null-free code can call the same APIs in those cases where parameters are
>> permitted to be null. [See note 2.] Name clashes would need to be addressed
>> of course. Nulls return values could be similarly auto-(un)boxed.
>>
>> The nullness markers ! and ? are also not going to help with non-nullable
>> value types and the associated sought-after compactness in memory that can
>> be achieved with such types. With non-nullable value types the fact of
>> non-nullability is a property of the type, not of the code using the type.
>> It can't be anything else since a non-nullable type must always have a
>> value of some sort necessitating a default constructor.
>>
>> I use a lot of non-nullable value types and the non-null requirement that
>> supports memory compactness comes at a high cost. I don't think most
>> programmers realise that. This is because to achieve compactness, null
>> itself needs to be removed, but the requirement for representing the null
>> case does not go away. For each non-nullable value type I have found it
>> necessary to define at least one value of the type to represent
>> not-a-value. This is usually the default value that is generated by the
>> type's no-arg constructor. It is then useful to have a method for
>> determining if an instance represents a value, or not-a-value, e.g. boolean
>> isValue(). For every method implemented on such a type, except the
>> isValue method, it is then necessary to check for validity and throw an
>> AttemptedUseOfNonValue exception if the instance is equal to the
>> not-a-value value. In type hierarchies, it has often been necessary to
>> define a subtype that is NotAnXXX to represent the not-a-value case, and
>> all of the methods of this subtype (except isValue) automatically throw
>> the AttemptedUseOfNonValue exception. The values representing the null case
>> for non-nullable value types also litter switch statements. That is to be
>> expected. The null case *is* a case.
>>
>> I have included the comments on compactness to make it clear that while
>> nullability and compactness are both about how null cases are represented,
>> they are in fact very different problems and they can and do have very
>> different solutions. Solutions that are decoupled from one another in terms
>> of how a programmer works with them.
>>
>> *In summary I suggest*:
>>
>> - Regarding nullability
>> - Eliminate nulls in favour of Optional.
>> - Do not introduce the nullness markers ! and ?.
>> - Add modifiers to ask the compiler to enforce use of Optional and
>> eliminate nulls.
>> - Use Optional boxing/unboxing to permit null-free and legacy code
>> to use the same APIs as far as possible.
>> - Regarding compactness:
>> - Implement non-nullable as a class modifier at least for value
>> classes.
>>
>>
>> *Concluding remarks*:
>>
>> I am a Java programmer with a mixed style, not a pure functional
>> programmer. Even so I largely avoid nulls by using Optional, sealed types,
>> and other techniques. My experience suggests that the easier, more
>> developer friendly, more Java compatible approach is to enforce use of
>> Optional and eliminate nulls altogether rather than embark on the ! and ?
>> route to cope with them.
>>
>>
>> Best wishes,
>> Jeremy.
>>
>>
>>
>> Note 1: With Java's almost miraculous modern garbage collection, value
>> classes and the possibility of flattening coming to Java, other approaches
>> look irrelevant in an increasingly large number of situations.
>>
>> Note 2: Going forward new APIs should not accept nulls. In general a
>> method with optional parameters indicates that the method has more than one
>> use case, which is usually better handled by method overloading or by using
>> an interface object that with optional parameters. Legacy is one thing, but
>> I don't think we should see much use of Optional in method parameter lists
>> going forward.
>>
>>
>>
>>
>>
>>
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-spec-observers/attachments/20251113/62e4b0b5/attachment.htm>
More information about the valhalla-spec-observers
mailing list