Kotlin solved Java's problem by making it a compiler error if a value that can be null isn't checked and shown to be null or the actual value, eliminating an entire class of exceptions.
I confess I’m not fond of checker framework. I find the error messages can be obtuse but it is very effective.
The problem with nullability annotations in Java is that they are not enforced, and there is no commonly adopted standard. There are like ten competing libraries with similar annotations. There was JSR 305 ("Annotations for Software Defect Detection"), but it has been dormant. When you import a third party library, you never know what kind of nullability annotations it uses and if it uses them at all.
String foo = null;
String bar = "";
foo.equals(bar) --> true
This works well provided the data type has a sensible zero value like collection typesEDIT: I'm blocked from posting so I won't be responding further, thank you for discussion.
Go: *string
Java: Option<String> or @Nullable String
Rust: Option<String>
TypeScript: string | undefined (or string | null)Rarely do you have a textual database column where the empty-vs-NULL distinction is semantically meaningful in the application domain. Most of the time, either the column value is missing (arguably better represented by NULL) or has a non-blank value. “Present but blank” is rarely meaningful or useful
Sometimes I pair that with (TRIM(column)=column) to prevent leading or trailing whitespace being saved, which also stops all-blank values being saved
This works really well if you have an RDBMS which supports CREATE DOMAIN, so then you can attach these constraints to a user-defined type and don’t have to repeat them for each column, you just set the type of the column to that user-defined type
Not if you use Oracle.
Similarly an Option<byte> has 257 different values while a byte has 256 different values. That the byte has a good zero value doesn’t change that - the whole reason for choosing a maybe-byte is having 257 values, not 256.
As the example of byte vs option<byte> either you want 256 states or you want 257. If you have 256 or 257 states you want to represent will decide which type is correct. The other choice of type is incorrect.
In some languages, these things are blurred because the language doesn’t let you choose a correct type for the state space, but I’m talking about the case where you can (coincidentally the set of languages I’d use).
E.g a boolean in java has two states true/false while a Boolean with capital B has 3 states true/false/null.
In that context you can choose type to represent how many states you have. E.g if it’s a field representing a cache of a bool value you can represent “not yet calculated” with null. It you were to magically convert null to false for a Boolean it only has two states! It’s now unusable for the purpose.
You need a 257th value to have a byte sentinel.
The whole point is to track the absence of a value. Why would one want to eliminate it?
null is way more trackable that some other special value like 0, -1, 999, "", etc.
To put this in more concrete terms, if this change were integrated in Java, how would you indicate the difference between a JSON document which doesn't contain a field VS one where the field is an empty string?
I base this mostly on an assumption of C still being one of the most widely used languages for the code that's running out there in the world. In C, after all, NULL is just a magic value rather than a distinguishable representation of no value, though that's just one example out of a host of others, all the way down to the venerable NUL-terminated string.
As for your question: something like 'keys(jsonobject).contains("fieldName")' ? Or 'NoSuchFieldException' thrown if you do 'jsonobject.get("fieldName")' ?
(The latter of which, given the general uneasiness NullPointerException creates in us devs, is often how a Java API will work anyway! Checked exceptions won the day! Until the Functional interface was made, at least.)
Or to answer it in the same spirit as this overall comment, why would you need to distinguish between missing and empty? Can't you just define the semantics of the document s.t. those two things having the same effect?
> As for your question: something like 'keys(jsonobject).contains("fieldName")' ? Or 'NoSuchFieldException' thrown if you do 'jsonobject.get("fieldName")' ?
> (The latter of which, given the general uneasiness NullPointerException creates in us devs, is often how a Java API will work anyway! Checked exceptions won the day! Until the Functional interface was made, at least.)
I was thinking more of the case where you deserialize a JSON object into a Java object, and then inspect the Java object. Regardless, it was just an example - the problem of distinguishing "no value" from "any value" is pervasive in programming, and all languages must have some strategy for it. If we got rid of null from Java, then Option<T> would probably be the only general candidate. Which, to be fair, would be slightly better, as it would at least force you to check.
> Or to answer it in the same spirit as this overall comment, why would you need to distinguish between missing and empty? Can't you just define the semantics of the document s.t. those two things having the same effect?
Not in the general case, no. At least not without doubling every field and adding other inconsistency issues ({"result": "ABC", hasResult: false}).