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

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.

Related

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.

What different StringBuilder and StringBuilder! in kotlin? [duplicate]

This question already has answers here:
Single exclamation mark in Kotlin
(7 answers)
Example of when should we use run, let, apply, also and with on Kotlin
(6 answers)
Closed 2 years ago.
In the code below. I found in Intellij Idea compiler that val a and val b by default are "val a: StringBuilder" & "val b: StringBuilder!"
what is the difference between the two? What's the difference between StringBuilder and StringBuilder! ? Thank you :)
fun main(){
val a = StringBuilder().apply { // by default is val a : StringBuilder
append("Hello ")
append("from me")
}
println(a)
val b = StringBuilder().run { // by default is val b : StringBuilder!
append("Hello ")
append("from me")
}
println(b)
}
The ! indicates a platform type. It means that the compiler can't tell whether the type is nullable or not, because it comes from Java (or another JVM language), which doesn't make the distinction between nullable and non-nullable types, and doesn't have an annotation (#Nullable or #NonNull) to indicate that.
As a result, the compiler won't be able to make its usual null checks, so you should take care.
If you know (from the documentation, or looking at the Java code, or whatever) whether the value could be null or not, it's a good idea to specify the type explicitly (as either nullable with a trailing ?, or non-nullable without).
In this case, the difference is that apply() returns the value it was called on; that's all Kotlin, so the compiler knows its type. However, run() returns the last value in the lambda, which is the result of the last append() call. That method is defined in Java (since StringBuilder is part of the Java standard library), so the compiler can't tell whether it's nullable or not. But it's clear from the documentation that the method simply returns the StringBuilder it was called on, and so cannot be null. So for safety, you could specify an explicit StringBuilder type (i.e. non-nullable) for b.

What's use of nullable in Kotlin [duplicate]

This question already has answers here:
In Kotlin, what is the idiomatic way to deal with nullable values, referencing or converting them
(4 answers)
Closed 4 years ago.
I do not know what's use of nullable in some case in Kotlin. Let me hold an example.
There is a method.
fun hello(name: String)
As you see, the param name is non null. Then I will use it.
hello(bob!!) // bob is a nullable string
If bob is null, above code will throw KotlinNullPointerException. So I have to wrap check.
if(bob != null) {
hello(bob!!)
}
So in this situation, what's the best practice? And what's use of nullable?
It is a matter of you code business logic to decide.
Usually you will want to use the '!!' operator in case you are 100% sure that bob is not null. In that case '!!' is a clean non-verbose way to ignore the option that 'bob' is null.
If there is a chance that bob is null, use if/else or in case that it is a business error it is advisable to throw an appropriate business exception or handle it in the usual way you are handling errors in your project.
This is how you would use such a function:
fun hello(bob: String) {
println(bob);
}
hello("Bob!!");
What this means is that the function hello has a parameter named bob, with a datatype of String.
In your example, you are giving the hello function a variable that has not been declared (bob), and as such the JVM cannot pass along anything but null. If you want to pass in a variable named bobby, the code would look like this:
fun hello(bob: String) {
println(bob);
}
val bobby = "Hello!!!";
hello(bobby);
Hope this helps in your endeavors :)
What's use of nullable?
Take for example a boolean variable which can only hold 2 types of values, true of false. There is no way to signify "undefined". Sometimes we need a way to tell that variable is in an undefined state. For eg, in database or network interaction, you may not receive any value so then variable has to exist in some undefined state and that's what null value signifies.
This not just applies to Kotlin, it applies to any language.
what's the best practice?
With nullable types, there is always a risk of null pointer exception, so better check for null before accessing it, and in here
if(bob != null) {
hello(bob!!)
}
no need to do bob!!, just bob will do, since you have done a null check, Compiler keeps track of the null check and will let you use that variable.
Use non-null assertion (!!) when you are absolutely sure the variable is not null and in that case, no need to surround with null check as well.

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

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.