Reputation: 2664
I'm new to Kotlin and I've read that it seems to be the best invention after the wheel. That makes me suspicious anyway, certainly because I didn't understand everything the concept implies.
To resume what I understood, before we had NullPointerException
so a very clear idea about something is wrong in the code and where the problem occurs but not where the null was set. Anyway, it was quite clear that we could wait here until the null pointer comes back expecting understand what happened from the backtrace. Everybody did that already, that's never impossible to find.
Now with Null Pointer Safety, we do not have such crash anymore, just some part the code which silently won't be executed in our application (we assume the reference used is not supposed to be null as before, of course), causing maybe strange behavior even more complicated to understand than the NullPointerException
before, or maybe just some tasks not executed for month before someone realize it.
Is it the benefits Null Pointer Safety offer?
Upvotes: 11
Views: 3891
Reputation: 7133
You don't need to not execute some piece of code due to a null object.
The benefits to a Null Pointer Safety system is that you can know beforehand if you might face a Null Pointer
, and act accordingly. You can know for sure if something might be null, and do something different.
For example:
var nullableServiceVariable: NullableService? = null //Let's say that you initialize this somewhere
var serviceAnswer = nullableServiceVariable?.answer ?: "Answer for null!"
The compiler makes you handle the possibility of null
, so you don't get an unexpected NullPointerException that stops all your application. If the nullable is indeed null, I'll give an alternative branch, so that my system is still functional.
If you want, you can throw a NullPointerException
, but it would be better to use a non-nullable variable instead:
var serviceAnswer = nullableServiceVariable!!.answer
!!
will throw a NPE for you if the variable is null.
Upvotes: 1
Reputation: 3826
To give you a short answer, your understanding is totally correct. Kotlin does not solve the NPE issue. It just proactively forces you to make an explicit decision to prevent it or not.
Upvotes: 3
Reputation: 1979
I will assume that you come from Java, you already looked at some explanations somewhere else and did not fully understand them. Therefore, I will not try to give you a comprehensive explanation (which you can find elsewhere) but instead I will try to make clear the core idea of null pointer safety.
There are two points that, if you understand them, should make it clear enough. First, there is the idea of having two separate types to represent what you would model as a single type in Java: nullable ones and not nullable ones. To give you an example, while in Java you put a string in a String
object, without caring if the string can be null or not, in Kotlin you have two types: String?
and String
. The first accepts null values (like the Java equivalent) but the second does not. So you can have null values in types with a ?
(like String?
or Int?
) but there are a lot of restrictions on what you can do with those: basically you are restricted to the things you can do with a null, because, after all, the variable could be holding a null value. So no calling of method on it, for instance. So, while in Java you could call a method on it and have a NullPointerException
sometimes, in Kotlin you cannot call any methods. And this is not because of some silent behavior of Kotlin, it’s much simpler than that: the compiler won’t let you. Try and you will see that the program does not compile. If the variable was of type String
instead of String?
then Kotlin would allow you to call methods from it.
So, basically, no null pointer exceptions because you can never call a method on an object variable that could be null.
But then, sometimes the variable is not null: so how could you call the method on the variable in those cases where the variable is not null? Again, the answer is simple: you have to check it. I mean, you have to use an if
instruction (explicitly or implicitly) that will check if the variable is null or not. Something like “if (myVariable != null) {call method on variable}
”. So, as you can see, the Kotlin compiler is clever enough to see that you used an if
instruction that guarantees that the variable is not null, so it will let you call methods on the variable in the block between {
and }
. In other words, if your variable is of type String?
but you are inside an if
block where you checked that the variable is not null, Kotlin will treat it like a variable of type String
instead of String?
When you speak about
some part the code which silently won't be executed
I am guessing you are thinking about some operators that have an implicit if
inside of them, like the ?.
operator. If you write
myVariable?.call()
it means roughly
if (myVariable != null) { myVariable.call()}
So, indeed, if the variable is null, it will “fail” silently. But this is not different than Java if you use the same kind of if
. In other words, nothing will happen if the variable is null because you explicitly coded it to behave like that.
Upvotes: 14
Reputation: 7001
In most languages, this would be allowed
val example: String = null
then later on you would do this:
print(example.toUpperCase());
You can see that the mistake is probably in the first bit of code, but the error happens at the second bit, which is confusing.
With null safety, when you define a variable you say if it will be null or not, and get a compilation (rather than runtime) error when this is broken.
It is still possible to get a null pointer, but the main way would be like this:
Create a nullable type
var r:String
Have the value as null
r = null
Assert the value is not null
r!!
This is why you want to avoid !!
unless you are sure the value will not be null.
You can deal with nullable types when you don't want null in many ways:
With a default
val set = nullable ?: "It was null, sorry"
Throwing if the value is null
val set = nullable ?: throw AssertionError(":(")
Propagating nulls
val set = nullable?.doThing()?.doThing2()?.property
set will be the final value, or null if any of these gives back a null
Only operating on nulls
nullable?.let {
print(it.property)
}
Upvotes: 2
Reputation: 97148
The main benefit is that the code which can potentially cause a NullPointerException
does not compile. The only situation when you get "part of code which silently won't be executed" is when you use safe calls to deal with a potential nullability error. This is not the only, and not the most useful, way to deal with such errors.
Upvotes: 5