What's the difference between !! and ? in Kotlin?
KotlinKotlin Problem Overview
I am new to Kotlin. I want to know the difference between this two !!
and ?
in below code.
Below, there are two snippets: the first uses !!
for mCurrentDataset
and another having ?
for same variable.
if(!mCurrentDataset!!.load(mDataSetString.get(mCurrentDataSelectionIndex), STORAGE_TYPE.STORAGE_APPRESOURCE))
{
Log.d("MyActivity","Failed to load data.")
return false
}
if(!mCurrentDataset?.load(mDataSetString.get(mCurrentDataSelectionIndex), STORAGE_TYPE.STORAGE_APPRESOURCE)!!)
{
Log.d("MyActivity","Failed to load data.")
return false
}
Kotlin Solutions
Solution 1 - Kotlin
As it said in Kotlin reference, !!
is an option for NPE-lovers :)
a!!.length
will return a non-null value of a.length
or throw a NullPointerException if a
is null
:
val a: String? = null
print(a!!.length) // >>> NPE: trying to get length of null
a?.length
returns a.length
if a
is not null
, and null
otherwise:
val a: String? = null
print(a?.length) // >>> null is printed in the console
To sum up:
+------------+--------------------+---------------------+----------------------+
| a: String? | a.length | a?.length | a!!.length |
+------------+--------------------+---------------------+----------------------+
| "cat" | Compile time error | 3 | 3 |
| null | Compile time error | null | NullPointerException |
+------------+--------------------+---------------------+----------------------+
Might be useful: What is a NullPointerException?
Solution 2 - Kotlin
this is '!!' double-bang operator is always return not-null value and this is '?' safe call operator returns value if value is not null, and null otherwise
This is unsafe nullable type (T?) conversion to a non-nullable type (T). It will throw NullPointerException if the value is null.
It is documented here along with Kotlin means of null-safety.
ref - hotkey
Solution 3 - Kotlin
the precedence of operators !
, ?.
, !!
is ?.
> !!
> !
.
the !!
operator will raising KotlinNullPointerException
when operates on a null
reference, for example:
null!!;// raise NullPointerException
the safe call ?.
operator will return null
when operates on a null
reference, for example:
(null as? String)?.length; // return null;
the !!
operator in your second approach maybe raise NullPointerException
if the left side is null
, for example:
mCurrentDataset?.load(..)!!
^-------------^
|
when mCurrentDataset== null || load() == null a NullPointerException raised.
you can using the elvis operator ?:
instead of the !!
operator in your case, for example:
!(mCurrentDataset?.load(..)?:false)
Solution 4 - Kotlin
In Addition to what Alexander said and as shown in the docs too,
the ?.
safe call operator is very useful in chaining, something like this
student?.department?.hod?.name
if there is no student, returns null otherwise look for his department. If department doesn't exist returns null otherwise look for hod (head of department) and so on.
If any one of student, department or hod is null then the result will be null.
Solution 5 - Kotlin
Safe Calls operator
In Kotlin
var a = x?.length;
Equivalent code in Java
int a = valueOfInt();
int valueOfInt() {
if (x != null) {
return x;
} else {
return null;
}
}
Side chain rule
bob?.department?.head?.name
it can be read as->
If bob
is not null give me the department
,
if department
is not null give me the head
,
if head
is not null give me the name
.
If any of it is null
, then it returns null
? before Data type
If ? used before data type like:
val b: String? = null
it means you can assign null value to it otherwise null value can't be assigned to it.
The !! Operator
For those who like to have Null Pointer Exception (NPE) in their program.
val l = b!!.length
this will return a non-null value of b
if b
is not null OR throw an NPE if b
is null
Solution 6 - Kotlin
SafeCall Operator(?):
var a: String = "abc"
a = null //compile time error
val b: String? = null
val result = b?.length//returns null
Assertion Operator(!!):
val b: String? = "dd" //any value or null
val l = b!!.length
//this throws null pointer exception if b is null otherwise returns actual