What is the Kotlin double-bang (!!) operator? - kotlin

I'm converting Java to Kotlin with Android Studio. I get double bang after the instance variable. What is the double bang and more importantly where is this documented?
mMap!!.addMarker(MarkerOptions().position(london).title("Marker in London"))

This is unsafe nullable type (T?) conversion to a non-nullable type (T),
!! will throw NullPointerException if the value is null.
It is documented here along with Kotlin means of null-safety.

Here is an example to make things clearer.
Say you have this function
fun main(args: Array<String>) {
var email: String
email = null
println(email)
}
This will produce the following compilation error.
Null can not be a value of a non-null type String
Now you can prevent that by adding a question mark to the String type to make it nullable.
So we have
fun main(args: Array<String>) {
var email: String?
email = null
println(email)
}
This produces a result of
null
Now if we want the function to throw an exception when the value of email is null, we can add two exclamations at the end of email. Like this
fun main(args: Array<String>) {
var email: String?
email = null
println(email!!)
}
This will throw a KotlinNullPointerException

Not-null assertion operator
Kotlin's double-bang operator is an excellent sample for fans of NullPointerException (NPE).
The not-null assertion operator !! converts any value to a non-null type and throws an exception if the value is null.
val nonNull = str!!.length
If you write str!!, it'll return a non-null value of str (str is a String? here) or throw an NPE if str is null. This operator should be used in cases where the developer is guaranteeing – the value will never be null. If you want an NPE, you have to ask for it explicitly.

!!(Double Bang) operator is an operator to assert forcibly nullable variable as not null.
Example:
Here str is a string with value. But its nullable. Since its nullable we need to handle null for avoid compile time exceptions.
val str :String? = "Foo"
val lowerCase = str!!.lowerCase()
Here if we add !! operator, since it has non null value it would work and lowercased value will be assigned.
val str :String? = "Foo"
str = null
val lowerCase = str!!.lowerCase()
But here if you assign null value and use the particular value , it will throw KotlinNullPointerException.
One important thing here is, in most of the cases one should avoid as !! operator unless if its 100% sure that value is non null value or if the exception is caught and handled properly.
If you need to avoid this NPE, you can use null safe operators with elvis operators. null safe call ?. opertators with elvis are better way to handle null safety in kotlin.
You can read more about Kotlin null safety here

!! is an assertion that it is not null. Two exclamation marks after a nullable value convert it to a non-nullable type. At the same time, before the conversion, it is not checked in any way that the value really does not contain null. Therefore, if during the execution of the program it turns out that the value that the !! operator is trying to convert is still null, then there will be only one way out - to throw a NullPointerException.

Java
throws NullPointerException
Kotlin
simply use !!
This would help for understanding

It means in human language: I promise I will assign value later, but please don't worry for now my variable. On the other it is non-null variable terminologically.

Related

Is !! The same thing as ?. In kotlin? [duplicate]

This question already has answers here:
What's the difference between !! and ? in Kotlin?
(6 answers)
Closed 6 months ago.
I've read that using "!!" Instead of "?." In kotlin is not recommended. What is the difference between the 2 when checking for null in variables?
!! - is a developer's way of telling the compiler, trust me, I know this value will not be null. It is an unsafe way of converting a nullable value to a non nullable type. Unsafe meaning that it can throw a NullPointerException if the value is indeed null.
You can read more about it here.
?. - is a developer's way of telling the compiler that in the case where the value is not null, do the rest of the logic followed after the ?. sign. This way is the safe way to access a nullable type.
You can read more about it here
"?." and "!!" are not the same.
"?." operator also called safe call operator which is used to safely access properties from a nullable object
Refer to this link
Whereas "!!" is called a not-null assertion operator, it forcefully denotes a nullable type as not null. using this operator without any check for null will lead to NullPointerException.
Refer to this link
No both are different.
!! operator is called as double bang operator in kotlin. It means you are forcefully nullable fields as non nullable. It will throw NullPointerException when the particular nullable field is null.
var s :String? = null
var b :String = s!!.lowerCase() // It will throw null pointer exception as you are asserting nullable variable as non null
?. is null safe call operator. It is used for making null safe access to particular field.
var s :String? = null
var b :String? = s?.lowerCase() //Here lowerCase will not execute because you are making safe call only if value is not null.
var s :String? = null
var b :String = b?.lowerCase() ?: ""
Additional thing if you need to b as non null during safecall operator you can use ?: (elvis) operator to have default value if previous safe call statement is null.

How to safe-cast a null into a generic type <T>?

I want to know if there's a way to make a safe cast from null, the next example throws an UNCHECKED CAST warning:
fun <T> notInitialized(): T = null as T
So, If anyone has an idea of how to make a safe cast from this function please let me know!
You can do fun <T> notInitialized(): T? = null - you need to return a nullable type (otherwise your cast is explicitly unsafe), and since you're already specifying the return type you don't need to cast null as T?. Or you could do that and skip the return type, fun <T> notInitialized() = null as T?
Either way you're just returning null, which isn't any specific type - you're just telling the caller to treat it as one. And that type needs to be nullable
As an alternative to the generic answer (which is the usual way to approach these things), you could do this:
fun notInitialised(): Nothing? = null
Nothing is the ‘bottom’ type, which has no values and is the subset of all other types. So Nothing? is a type with just one value (null), and is a subtype of all nullable types. This means you can assign it to any nullable type without needing any type inference, e.g.:
val a: Int? = notInitialised()
But I still don't understand the purpose of this — it doesn't seem to have any benefit over just using null directly. If you're using null to represent an uninitialised value (as opposed to an unknown value, a missing value, an inapplicable value, an unavailable value, an undefined value, an unchanged value, a secret value, or any of the other subtly-different things that people use null to mean), then that should be spelled out in the property/method/variable's doc comment — in which case there's no point spelling it out again in the code.

Kotlin "let{}" Doesn't Provide Smart Cast

Just learned Kotlin Nullable type and let{} function which replaces the if (xx != null) {} operation.
But one thing I am confused is that, we all know and I Think the Complier Should Know that when we use let{}, the variable/object who is calling this function is possiblly null, however the complier still requires me to add the safe call operator "?" after the variable name instead of providing Smart Cast like it does in if (xx != null) {}. Why?
My piece of code:
fun main() {
var number1: Int? = null
//val number2 = number1.let { it + 1 } ?: 10 //doesn't work, not quite "smart"
val number2 = number1?.let { it + 1 } ?: 10 //works, must have "?"
println(number1)
println(number2)
}
You've already got answers in the comments, but just to explain the ? thing...
Kotlin lets you make null-safe calls on nullable variables and properties, by adding ? before the call. You can chain this too, by doing
nullableObject?.someProperty?.someFunction()
which evaluates nullableObject, and if it's non-null it evaluates the next bit, otherwise the whole expression evaluates to null. If any part of the chain evaluates as null, the whole expression returns null.
So it has this short-circuiting effect, and you can use the elvis "if null" operator to create a default value if you can't evaluate the whole chain to a non-null result:
nullableObject?.nullableProperty?.someFunction() ?: defaultAction()
and once you introduce the null check in the chain, you have to add it for every call after that - it's basically propagating either the result of the previous bit, or the null it resolved to, so there's a null check at each step
The let block is just a scope function - you use it on a value, so you can run some code either using that value as a parameter or a receiver (a variable or this basically). It also has the side effect of creating a new temporary local variable holding that value, so if the original is a var it doesn't matter if that value changes, because your let code isn't referring to that variable anymore.
So it's useful for doing null checks one time, without worrying the underlying value could become null while you're doing stuff with it:
nullableVar?.let { it.definitelyIsNotNull() }
and the compiler will recognise that and smart cast it to a non-null type. An if (nullableVar != null) check can't guarantee that nullableVar won't be null by the time the next line is executed.

I'm unable to remove my NullPointerException error

The below code
fun main(args: Array<String>) {
println("Enter your value : ")
try{
val(a, b, c) = readLine()!!.split(' ')
println("Values are $a $b and $c")
}catch(ex : IndexOutOfBoundsException){
println("Invalid. Missing values")
}
}
produces the following error in Kotlin Playground:
Enter your value:
Exception in thread "main" kotlin.KotlinNullPointerException at FileKt.main(File.kt:4)
I have seen other questions with NullPointerException but I am unable to resolve it. I might would have missed some so it would be really helpful if you can share useful links. Since I am new to Kotlin, it would be awesome if you correct my program.
Remark: I don't have any background on java either and most of the NullPointerException questions are based on java
Edit 1 : I have tried gidds' solution and it seems to be working except one minor fault. The readLine() is for some reason not working.
The below code
fun main(args : Array <String>){
val line = readLine()
try{
println("Output : $line")
if (line != null) {
val(a, b, c) = line.split(' ')
println("Values are $a $b and $c")
} else {
println("No values given...")
}
}
catch(ex : IndexOutOfBoundsException){
println("Invalid. Missing Values...")
}
}
produces the following error in Kotlin Playground :
Output : null
No values given...
I guess I was getting the previous errors due to the same reason, i.e. readLine() was not working properly and the user is not getting an opportunity to give input(s).
With readLine()!!, you are saying the compiler that if this returns null, that will crash with NullPointerException. In another way, you must be sure to have return value of readLine() to be not null. Read more about !! operator here.
The not-null assertion operator (!!) converts any value to a non-null
type and throws an exception if the value is null.
You can have null check with elvis operator like below:
try{
val(a, b, c) = readLine()?.split(' ')
println("Values are $a $b and $c")
}catch(ex : IndexOutOfBoundsException){
println("Invalid. Missing values")
}
To expand on the earlier answer, this is about how to handle nulls.
The problem is that readLine() can return null.  (This happens if end-of-file is reached; for example, if you redirect the input from a file, and reach the end of the file; or if it's taking input from the keyboard and you press Ctrl+D.)
The Kotlin compiler knows this.  (Nullability is built into Kotlin's type system.  readLine() returns a String? — the question mark indicates that the value could be null.)
Kotlin is very careful about null-safety, and won't let you do anything with the value that would fail if it's null.  So in your code, if you omit the !!, you get an error on the following ..  (‘Only safe (?.) or non-null asserted (!!.) calls are allowed on a non-nullable receiver of type String?’)
So you have to handle the null somehow.
Appending the not-null assertion !! effectively promises the compiler that you know better, and that it can never be null.  This is usually a bad idea (which is why that operator was designed to look ugly); in practice, you generally don't know better than the compiler, and it will trip you up — as you've discovered!  In your case readLine() did return null, and so the !! operator threw a KotlinNullPointerException.
So, you need a better way to handle it.
The traditional way is an explicit check, e.g.:
val line = readLine()
if (line != null) {
// Within this block, the compiler knows that line
// cannot be null.
} else {
println("No values given.")
}
This is a good, clear, general approach.  And it may be the best approach in your case.  (You'd still need to catch the IndexOutOfBoundsException, though.)
Because that approach can be a bit long-winded, Kotlin has some other tools that can be better in particular situations.  I don't think any are appropriate here, but I'll mention some for completeness:
One of those is the safe-call operator ?. given in the error message and the earlier answer.  This makes the call only if the value is not null; otherwise, it returns the null directly.  That can be really useful, but it's not a simple answer in this case, as your comment shows: although it avoids trying to split() the null, you then fail to deconstruct it into the three values a, b, and c.  (After all, null is not an array.)
If you wanted to substitute default values for a, b, and c if there was no input, you could use the safe-call operator in conjunction with the elvis operator ?:.  That returns the left-hand side if it's not null, else the right-hand side.  So you could do e.g.:
val (a, b, c) = readLine()?.split(' ')
?: arrayOf("defA", "defB", "defC")
println("Values are $a, $b, and $c.")
In this case, if readLine() returns a string, split() would be called on it; or if not, it would use the hard-coded array instead.
Note that this still isn't a complete solution, as it won't cope if you enter a line with less than two spaces.  (So you'd still need to catch the IndexOutOfBoundsException, or check for that case explicitly.)
(Perhaps the shortest solution overall would be to leave the !! intact, and change the catch block to catch Exception, so it would catch the KotlinNullPointerException along with the IndexOutOfBoundsException.  I'm not recommending that, as it's ugly: it's not clear to anyone reading the code what could happen and what exceptions you're intending to catch — and it could hide other problems in the code if they also resulted in exceptions.)

What is the difference between nullabe and non-nullable type in Kotlin

Please explain the difference between nullable and non-nullable type. I am new to kotlin and i am confused. Thanks
Nullable types can hold nulls. When type is nullable the question mark is set after it's type:
val str: String? = null
Non-nullable types can't hold nulls:
val str: String = "some value"
If we try to set null value to Non-nullable type, IDE will give an error and code will not be compiled:
val str: String = null // error, the code won't compile
Here you can read more about Null Safety.
when a variable has a nullable type then the variable can have value or it can also have value null and the program will not force close like most java based programs with null pointer exeption error messages.
for example :
val data: DataResponse? = null
its more save then you use val data: String because when your data variabel dont have value or null when you use it your program not force close at that time.
you can use your data variabel like this:
your_text.text = data
and your code will not force close.
but if your code like this, it means nonNullable.
val data: DataResponse
your apps will force close at that time you use your variabel