> Kotlin has many features that make it better than Java. Most importantly, it is null-safe. In addition to that it makes it simple to enforce data-immutability, which is very difficult in Java.
Kotlin does have nullability handling yes, but it's a very limited special-case feature - it's a language-level builtin rather than something you can use in your own libraries. E.g. if you want to have an error message in the failure case rather than just null (i.e. some kind of Result type), you can't reuse any of the null-safety functionality (whereas in Scala or Ceylon you can write the same methods to work with either optional/nullable or result-like types).
Data immutability isn't at all difficult in Java. It's tedious (sprinkling "final" everywhere), but not hard.
> it's a language-level builtin rather than something you can use in your own libraries
The only people who still think that a library approach is superior to a compiler approach are Scala users.
I'll clarify this for you: if it's a library construct, it can be ignored. And as a matter of fact, there is nothing in Scala forcing you to use `Option`. You can completely ignore it and enjoy your time diagnosing NullPointerExceptions everywhere.
When a feature is enforced by the compiler, such as Kotlin and Ceylon, you don't get any easy way out: you have to think about null cases or you will not be able to compile your code. Period.
You're conflating two different issues. Yes, Scala allows null and yes, this is unfortunate, though it raises the question of whether there's any better way to do Java interop (you can either assume all Java calls are non-null unless checked, assume all Java calls are nullable and force checking, or trust annotations; all these approaches suck in their own way). It can be mitigated with WartRemover.
But the right way to represent absence - whether you call it null or option or something else - is clearly with a normal type that follows the normal rules of the language, not a special language-builtin type with special language-builtin rules. Some light syntactic sugar for commonly-used types makes sense (like Ceylon's "?"), but what it desugars to should always be something you could write a normal library type for. Indeed if your language doesn't let you implement the constructs you need for this kind of type in a custom type in a library, that should be a red flag that your language isn't expressive enough for general-purpose use.
> (you can either assume all Java calls are non-null unless checked, assume all Java calls are nullable and force checking, or trust annotations; all these approaches suck in their own way)
Agreed, which is why Kotlin has explored all of these options and ending up implementing neither.
Kotlin does have nullability handling yes, but it's a very limited special-case feature - it's a language-level builtin rather than something you can use in your own libraries. E.g. if you want to have an error message in the failure case rather than just null (i.e. some kind of Result type), you can't reuse any of the null-safety functionality (whereas in Scala or Ceylon you can write the same methods to work with either optional/nullable or result-like types).
Data immutability isn't at all difficult in Java. It's tedious (sprinkling "final" everywhere), but not hard.