5 ms·
I've never used kotlin, but after reading the article, I wondered how it could be possible for kotlin to be null-safe and interoperable with Java at the same ti
by anorwell 9y ago
I've never used kotlin, but after reading the article, I wondered how it could be possible for kotlin to be null-safe and interoperable with Java at the same time. Turns out it's not [1]. Kotlin's null vs non-null types seem to be semantically the same as option vs non-option (as in scala). However, Scala allows any variable to be null separately from the type system, whereas Kotlin does not. It's not clear to me that Kotlin's approach is preferable here. Kotlin code that interfaces with Java gives the illusion of null-safety, but won't actually provide it. Scala does not attempt to provide this guarantee, which I don't think any language that interoperates with java can ever provide.
[1] https://kotlinlang.org/docs/reference/null-safety.html https://kotlinlang.org/docs/reference/null-safety.html
- bluejekyll 9y agoThis might be a better link based on your concern: https://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types https://kotlinlang.org/docs/reference/java-interop.html#null... This feels like a trad-off between ease-of-use/adoption. It's effectively undefined behavior to reference a nullable type from Java. Another way to consider this is that it's not necessarily worse than working natively in Java, but it can over time be better. This trade-off seems reasonable, as there is no great answer to this problem, but it's almost identical to Java's auto-unboxing of Integer types to int.
- vbezhenar 9y agoYou can annotate Java code with @Nullable annotations. Kotlin will understand it and interop will be safe. Spring does it for example, AFAIK Guava does it as well. It won't work with Scala. Another advantage over Scala is that Kotlin compiler puts null checks on boundaries between Java and Scala, so even if your code pretending to be safe breaks in runtime, you'll catch error as soon as possible, this null won't leak into your internals to bite you tomorrow. But that's certainly a thing that could be improved. Majority of Java parameters/return values nullability could be automatically inferred by analyzing bytecode.
- dep_b 9y agoInteresting. A bit worse than Swift and Objective-C. Objective-C has to promise `nonnull` otherwise it's shown as `ObjectType!` which basically means we treat it as non-null but it could be null and can be checked for null. Methods marked `nonnull` can still be nil sometimes, it's just a promise. Hard bugs to fix. Found one in an Apple framework where I could not think of anything else than comparing the address with 0x00000000 to see if it was nil.
- hinkley 9y agoI think you just assume everything in the JDK can return or take null. It's close enough to true.
- vbezhenar 9y agoThat's wrong, a lot of JDK api doesn't return null (and a lot of API throws NPE for null arguments). Assuming that everything can return or take null would make Kotlin code unnecessary verbose. It's a valid approach, but not the most pragmatic one.
- imtringued 9y agoI assume it inserts an automatic nullcheck [1] if you assign the return value of a java method into a non-null kotlin variable. You might still see NPEs but they happen exactly at the interop boundary between java and kotlin. When you do get an NPE the fix is obvious and trivial to implement. With scala the NPE could appear after the null crossed the java/scala boundary deep into scala code where you'd assume it should be impossible to get an NPE. It can sometimes be hard to fix because the problem is far away from the cause. [1] https://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types https://kotlinlang.org/docs/reference/java-interop.html#null... >If we choose a non-null type, the compiler will emit an assertion upon assignment. This prevents Kotlin's non-null variables from holding nulls. Assertions are also emitted when we pass platform values to Kotlin functions expecting non-null values etc. Overall, the compiler does its best to prevent nulls from propagating far through the program (although sometimes this is impossible to eliminate entirely, because of generics).
- s4vi0r 9y agoWhat do you mean? I've yet to deal with an NPE in either language. I mean, its possible, but you'd have to be trying pretty hard to get one IMO.
- JamesFM 9y agoI have been coding in Kotlin and using the interopt for various libraries. Typically you want to model things interacting with what Kotlin calls “platform types” as nullable. So for JPA entities, each field is marked as nullable, because in Java it is. If we need a null checked version we map it from the nullable fields object to a object that has been null checked and has non-nullable fields (where appropriate). Wrappers can be written to interact with more traditional Java libraries that do a similar null check and mapper, keeping platform types from propergating intro other layers of the system. Platform types make interopt way easier, but if you are concerned with null safety you have to write some code to deal with them.
- mmirate 9y agoMeanwhile, there are many other modern ML derivatives (e.g. Ocaml, Rust) which aren't encumbered by the limitations of VMs designed for wholly-imperative languages.