I'm currently in the process of switching over from java to kotlin and one of the stated advantages that keeps popping up is that kotlin is Null safe and by default cant have variables or objects be assigned a null value but there are ways to assign a null value. However I'm not sure why this is beneficial what problems arise from Java not being null safe?
Thus far online searches have only yielded descriptions of what null safety is and not why it was implemented. Thanks in advance.
CodePudding user response:
It's fundamentally a typing issue.
You might as well ask this question which is entirely analogous:
"I'm currently in the process of switching over from javascript to java and one of the stated advantages that keeps popping up is that java is typed and cant have variables or objects be assigned a value of a kind you weren't expecting. However I'm not sure why this is beneficial what problems arise from Javascript not being type safe?"
Let's say I write this method. Simple enough:
public boolean areBanksOpen(LocalDate someDate) {
...
}
This method checks the books about official national holidays and whatnot. In your mind you should create the notion that the author of some part of the code is different from the author of some other part of the code. Even for projects that only one person works on: Then its you, writing some code three years ago, vs. you using that code today. You don't remember (or shouldn't have to remember) every nook and cranny of that code as you wrote it back then.
Given that it's not the same person, communication is incredibly important. You need to communicate from the author of areBanksOpen
to the user of that method: What is it called, what does it do, how do you use it? Yes, you can write a gigantic tutorial, of course, but communication is a little more complicated than that; if 95% of your programming hours are spent reading tutorials in webbrowsers, that's not good. A quick reminder, as well as 'training wheels' from your editor environment that detect errors you make are good things to have.
In java, the typing does that. In java, you can't write areBanksOpen("10-12-2021")
. Your editor will instantly tell you this is not going to work, you have to specify a LocalDate
instance, not a String
. In javascript you have no idea until you run it.
nullity is the same way. There is no way for the IDE or someone perusing the javadoc to figure out that the areBanksOpen
method accepts null or not. Can I call areBanksOpen(null)
, or not? Same for return types: Given a method String getStudentName(StudentId studentId)
, can null
even be returned?
In that sense all types in java are really That | Null
- as in, that getStudentName
method returns "Either a String or null", as in, that's what the signature means, even if the docs call out: This method throws some exception if studentId
isn't found, and all students have an ID (thus implying: No, this method never returns null). The method signature does not convey that information, only the docs do. Exactly analogous to how a method in javascript:
/** Pass a date object, returns a boolean whether banks are open */
function areBanksOpen(date) { .. }
in javascript explains how it works in the docs but the signature itself doesn't provide this information, which means [A] the editor can't be a second pair of eyes because editors don't read documentation but they can understand signatures, and [B] you don't get the benefit of quick lookups in auto-complete boxes and the like.
That is what the advantage is about: In kotlin you DO know, as does your editor
HOWEVER, the ones who told you this are misinformed. Java has this too, it's called nullity annotations. In java you do something like:
public boolean areBanksOpen(@NonNull LocalDate when) {}
and then IDEs will insta-redline any attempt to call areBanksOpen(null)
or areBanksOpen(someVar)
where simple code analysis shows that someVar
might contain a null
value. That's not a reason to switch to kotlin.
CodePudding user response:
Without null-safety...
It's easy to forget a member reference in your class might be null. If you use what you think is an object reference but it's actually null you get a NullPointerException.
There's no compiler-enforced way for a method to declare it is only able to handle non-null parameters. The author can mark it with some annotation or put a note about it the documentation of the method, but null values could still be passed through and cause a NullPointerException or other Exception of the author's choosing.
There's no compiler-enforced way for a method to declare it might return a null value. The author can mention it in the documentation or put some annotation on it, but if you fail to notice these or forget, you might try to use a null return value as an object reference and cause a NullPointerException.
Code that once worked could stop working and start causing NullPointerExceptions if a method that used to never return null starts sometimes returning null. Since it's not enforced by the compiler, you get the exception at runtime instead of getting a compiler error so you can fix it.