(Turn) [Kotlin] Null Safety

Reprinted from: http://blog.csdn.net/hp910315/article/details/50790681

 

One of the biggest differences between Kotlin and Java is that it strives to eliminate the dangers posed by null references. In Java, if we try to access a member of a null reference may result in the occurrence of NullPointerException (NPE). This problem is solved in Kotlin language, let's see how it is done.

In Kotlin, the type system distinguishes between nullable types and non-nullable types. For example, String is a non-nullable type and String? is a nullable type. If a non-nullable type is assigned null, it will not compile.

var a: String = "abc"
a = null // compilation error

var b: String? = "abc"
b = null // ok

 

 For non-nullable types, you can directly call its member variables or functions, but for nullable types, directly calling member variables or functions will fail to compile, which is equivalent to solving the restrictions directly at the syntax level.

Then the problem comes, because the nullable type will not compile when calling member variables or functions, but the nullable type can only be a null reference or not, and the compiler will do it all directly. Otherwise, if a nullable type itself It is not empty, we want to call its member variables or functions, but the compilation fails, which seems to be illogical.

E.g:

var a: String? = "abc"
val l = a.length  //compilation error

 The above code is logically no problem, but the compilation fails because String is a controllable type, and the compiler does not let it directly call member variables or functions. For possible types, if you want to call its member variables or functions, you must judge. Only, otherwise the compiler will not pass. This is how Kotlin solves null pointer exceptions. It will require programmers to avoid null pointer exceptions to the greatest extent possible.

var b: String? = "abc"
val l = if (b != null) b.length else -1

 There is no problem with the above code, because we have done the check, so the compiler allows to call the member variable of the nullable reference b.

For nullable references, if we want to call its member variables or functions, we must first check, otherwise the compiler will report an error.

E.g:

if (b != null && b.length > 0)
  print("String of length ${b.length}")
else
  print("Empty string")

 For this kind of restriction, there are good and bad, it feels a little rigid and a little troublesome. If you use a non-null reference, you must ensure that it is not null. This is acceptable. Use a nullable reference, and you have to check every time, which is very troublesome. , Haha, the designers of the language certainly wouldn't be so embarrassing. For simple use, there is a safe way to call nullable references, use ?. to call.

var b: String? = "abc"
b?.length  // ok

 In this way, you don't need to check, someone did it for you, if b is a null reference, return null directly, otherwise, return b.length. Keep it simple!

The specificity of the Kotlin language is simplicity. Everyone should pay attention to the fact that the above statements do not have semicolons. This is absolutely impossible in Java, but in Kotlin, you are so capricious. Do you remember the ternary operator in Java, there is a similar one in Kotlin.

val l: Int = if (b != null) b.length else -1
//Equivalent to
val l = b?.length ?: -1

 Returns -1 if b is null, otherwise returns b.length.

Calling of nullable references, there is a third aspect below to call its member functions and variables.

var b: String? = "abc"
val l = b!!.length()

 Its return value has two possibilities, if b is not null, return b.length(), otherwise, throw a null pointer exception, if b is null, you don't want to return null, but throw a null pointer exception, you can use it.

The following summarizes: 
1. Kotlin has two types: one is a non-null reference type, and the other is a nullable reference type. 
2. For a nullable reference, if you want to call its member variable or member function, a compilation error will occur if you directly call it. There are three ways to call: 
(1) Before calling, you need to check first, because it may be null 
(2) Use Called in the form of b?.length, if b is null, return null, otherwise return b.length 
(3) Use the form of b!!.length() call, if b is null, throw a null pointer exception, otherwise return b .length

In addition, we know that type conversions may generate ClassCastException exceptions, such as:

var a: Long = 1
val aInt: Int? = a as Int  // java.lang.ClassCastException

 So how to avoid this exception? Change it to the following form.

var a: Long = 1
val aInt: Int? = a as? Int

 The above method is a safe type conversion. If the type conversion is unsuccessful, it will return null instead of throwing a ClassCastException.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326053471&siteId=291194637