I am really not convinced by the NPE problems argu...
# announcements
p
I am really not convinced by the NPE problems argument. 1. I have rarely if ever had a Java program blow up due to NPE. 2. Kotlin's protection from NPE ends whenever you use platform types. Those are not solved satisfactorily IMO.
Copy code
var res = someJavaFuncThatActuallyReturnsNull()
// res is now SomeJavaType!
// at this point I can start passing 'res' around and later access anything on it and get an NPE, Kotlin didnt help at all
s
explicitly define type?
p
but the compiler does not force me to do so, so whats the point?
I can now have my project completely polluted with ticking time bombs ready to throw NPE any second. Any perceived null safety is now moot.
s
I think it's to be more convenient for the java libraries. If those libraries use annotations like findbugs's then kotlin automatically interprets return types
a
it'll work with jsr305 annotations
s
any quite a few others, lombok and jetbrains's of course
p
Assume the 3rd party library has no such annotations. Even Java stdlib is missing them.
What then?
s
I believe some exceptions, beyond the scope of this question are made in kotlin compiler
a
read the javadocs and then trust it up to date and dereference as nullable or not nullable
s
In the case of Java stdlib. As for third parties, well then you'll have to explicitly define types
var res: ReturnType = someJavaFuncThatActuallyReturnsNull()
Would error if it returns null there
r
@poohbar You may be the outlier on this topic, considering pretty much everyone else who uses Kotlin seems to fall in love with the null safety first and foremost. Maybe you just wrote much cleaner Java than most?
p
No, I don't have to do anything. The compiler does not enforce it. And that's the mistake I am pointing out.
s
The guy who invented null reference even regrets it himself 😂 https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions
p
Ruckus, I think the null safety is a swell idea but I think it's sad that it's not consistently enforced for platform types as well.
s
@poohbar because it doesnt know if the type is nullable or not, because those libraries did not use tools to provide metadata to methods and other features of the language
I believe it is much better than requiring you to explicitly specify nullsafe types with
!!
every time you make a java call
p
What? All the compiler needs to know is "this type is not coming from Kotlin and there are no annotations to help me, I must ask the user to provide the type explicitly" .. Are you saying this could not be done?
s
Oh i see. Well I'm sure there's further reason to why it wasn't done. Maybe they decided it would interfere with their "dynamic" property types or whatever they're called
a
@poohbar it used to be enforced, but it was too much of a hassle to work with, especially when you’re just starting to migrate Java project to Kotlin and have to have lots of Java interopish code
p
Artem, was it really the way I am talking about? Enforcing explicit types on vals and vars for java calls would completely lock down the null-safety across the whole project. The cost seems very minimal to me. I think what you are talking about was when they tried to infer null/non-null type from the annotations or by analysis. I am saying make the dev specify it!
Honestly, I would be happy with an IDE warning or suggestion.
👏 1
a
go ahead and write your own inspection
a
@poohbar developers were enforced to specify nullability before, it was hard to write code that used Java interop https://blog.jetbrains.com/kotlin/2014/10/making-platform-interop-even-smoother/
p
Artem, maybe I am not making myself clear but this is not what I am talking about. They say "so Kotlin has treated Java types as nullable". This is not what I want.
a
As far as I remember you could specify nullability or it’ll be nullable, this is basically what you want
p
MyClass.java
Copy code
public class MyClass {
    public Date getToday() {
        return null;
    }
}
test.kt
Copy code
fun main(args: Array<String>) {
    val mc = MyClass()
    val today = mc.today
    today.day.print() // BOOM NPE!!!
}
There are no warnings, no IDE suggestions, nothing. I am saying that the
val today
should not be allowed without explicit type. That's all.
a
🙂 I understand, that’s exactly how it was before and not that many users liked it, so we have what we have now
p
Ok, I will file a feature request to at least add the IDE warning. Because this makes the whole NPE safety absolutely moot and I am surprised more people don't see it. I have yet to write Kotlin program that would not interact with Java.
j
@poohbar if you don't mix Java and Kotlin, the null-safety is solid. We write everything from scratch and the thing for which we do use external libraries, we write Kotlin wrappers for which does the null checks to and from the Java code
👍 3
p
I understand, but you can't ask me to write a wrapper for every Java lib I use just because of null safety. That is a lot of work that could be done by the compiler.
j
as I said, the only Java lib we currenlty use is VertX, and we have extension methods on top of VertX which does a lot of things including making sure that we don't get hit by NPE.
a
ask someone to write such inspection in youtrack or write and publish your plugin
p
Sure, I guess your use is different. For me, Kotlin is interesting especially because of its super smooth interop with Java and all the Java libs I can use. I think we should not advertise Kotlin as a null-safe language until this gaping hole is fixed.
j
Pure Kotlin is null-safe, it's Java that is not
a
exactly
j
if you interface with C/C++ libs via JNI, you will face similar issues, you can't guarantee anything when interfacing with external languages
p
Like it or not, Kotlin is very much a Java 2.0 and is heavily Java oriented. It even reuses the same collections. I think the platform type situation should be improved.
a
kotlin is not just java, you can transpile it to javascript, and there's also kotlin native
j
with Java you have GWT which does the toJS, same for native I believe when using LLVM
Java 2.8 or 2.9 might be closer to the right version
p
@abreslav said in the comment regarding the M9 release that some warning will be included later, yet in the simple example above I get zero warnings and I am free to pass the val around until it blows up with a million dollar loss later down the line.
works for functions
j
@poohbar if you're running mission critical code and using Java libs in Kotlin code, it's worth writing wrappers. You're probably only using a few dozen Java methods, so you can have a single class that with 50 lines of code that calls java methods and sanity checks the results coming back.
a
vote that issue to make it work for local variables
j
have written 120k lines of Kotlin over the last 4 months in one project which does make use of several Java libs, a couple of wrappers and have not had a single NPE
i
@poohbar Note that requiring explicit types for variables when assiging values of platform types won't help you, if you do not use intermediate variable:
Copy code
val mc = MyClass()
mc.today.day.print()
c
@poohbar have you looked at how Scala deals with nullity? does not have this problem, but it is different.. I did not know about this as I have been doing pure K. Interesting..
p
@janvladimirmostert How do your wrappers solve the issue noted by Ilya above?
j
@poohbar by assuming that the result coming back from Java can always be null and checking for it. Simple example:
Copy code
fun String.indent(): String = StringUtils.indent(this) ?: ""
or alternatively:
Copy code
fun indent(input: String): String = StringUtils.indent(input) ?: ""
p
But what if the java lib returns a complex type with nested objects.. those could be null even if you wrap the return type.
j
do you have control over that Java class ? If so, use the @NotNull annotations If not, then your options are to wrap the methods and clone the data into Kotlin objects (not very efficient) or be forced to null-check everything on that object the whole time. We don't have any data-classes in Java, so this has not been an issue for us.
a
It would be nice if Kotlin warned you when when assigning platform types to non-null properties. Like for example:
Copy code
class ExampleActivity : Activity {
    lateinit var array: IntArray

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        array = intent.getIntArrayExtra("array")
        // throws IllegalStateException: getIntArrayExtra("array") must not be null
    }
}
d
@arekolek There's no distinction between non-nullable and nullable properties in java. As far as I remember docs for
Intent.getExtra
states that result MAY be null, if it's not there, thus you should just know your API.
In kotlin based code, on the other hand, the warning is there.
a
In kotlin based code, on the other hand, the warning is there.
What do you mean by that? Do you mean assigning nullable type to non-nullable? That’s an error, not a warning.
There’s no distinction between non-nullable and nullable properties in java.
But Kotlin treats non-annotated Java types as “platform types” and:
When a platform value is assigned to a Kotlin variable, we can choose the type that we expect. 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.
What I’m saying would be nice, is that if there was a warning (not an error) when assigning platform to non-null. Or at least some Lint check for that. That way, you could for example use the
!!
operator to mark that place as safe, or treat it as nullable instead, depending on the API you are using.