简体   繁体   English

在Kotlin无效检查的最佳方式?

[英]Best way to null check in Kotlin?

Should I use double = , or triple = ? 我应该使用double = ,还是triple =

if(a === null)  {
//do something
}

or 要么

if(a == null)  {
//do something
}

Similarly for 'not equals': 同样地,'不等于':

if(a !== null)  {
//do something
}

or 要么

if(a != null)  {
//do something
}

A structural equality a == b is translated to 结构相等a == b被翻译成

a?.equals(b) ?: (b === null)

Therefore when comparing to null , the structural equality a == null is translated to a referential equality a === null . 因此,当与null比较时,结构相等性a == null被转换为引用相等性a === null

According to the docs , there is no point in optimizing your code, so you can use a == null and a != null 根据文档 ,优化代码没有意义,因此您可以使用a == nulla != null


Note that if the variable is a mutable property, you won't be able to smart cast it to its non-nullable type inside the if statement (because the value might have been modified by another thread) and you'd have to use the safe call operator with let instead. 请注意 ,如果变量是一个可变属性,您将无法智能地将其转换为if语句中的非可空类型(因为该值可能已被另一个线程修改)并且您必须使用安全呼叫运营商改为let

Safe call operator ?. 安全呼叫运营商 ?.

a?.let {
   // not null do something
   println(it)
   println("not null")
}


You can use it in combination with the Elvis operator. 您可以将它与Elvis运算符结合使用。

Elvis operator ?: (I'm guessing because the interrogation mark looks like Elvis' hair) 猫王操作员?: 我猜是因为审讯标记看起来像猫王的头发)

a ?: println("null")

And if you want to run a block of code 如果你想运行一段代码

a ?: run {
    println("null")
    println("The King has left the building")
}

Combining the two 将两者结合起来

a?.let {
   println("not null")
   println("Wop-bop-a-loom-a-boom-bam-boom")
} ?: run {
    println("null")
    println("When things go null, don't go with them")
}

两种方法都生成相同的字节码,因此您可以选择任何您喜欢的字节码

Kotlin ways of handling null Kotlin处理null的方法

Secure Access Operation 安全访问操作

val dialog : Dialog? = Dialog()
dialog?.dismiss()  // if the dialog will be null,the dismiss call will be omitted

Let function 让功能

user?.let {
  //Work with non-null user
  handleNonNullUser(user)
}

Early exit 提前退出

fun handleUser(user : User?) {
  user ?: return //exit the function if user is null
  //Now the compiler knows user is non-null
}

Immutable shadows 不可变的阴影

var user : User? = null

fun handleUser() {
  val user = user ?: return //Return if null, otherwise create immutable shadow
  //Work with a local, non-null variable named user
}

Default value 默认值

fun getUserName(): String {
 //If our nullable reference is not null, use it, otherwise use non-null value 
 return userName ?: "Anonymous"
}

Use val instead of var 使用val而不是var

val is read-only, var is mutable. val是只读的, var是可变的。 It's recommended to use as many read-only properties as you can, they are thread-safe. 建议尽可能多地使用只读属性,它们是线程安全的。

Use lateinit 使用lateinit

Sometimes you can't use immutable properties. 有时您不能使用不可变属性。 For example, it happens on Android when some property is initialized in onCreate() call. 例如,当在onCreate()调用中初始化某些属性时,它会在Android上发生。 For these situations, Kotlin has a language feature called lateinit . 对于这些情况,Kotlin有一个名为lateinit的语言功能。

private lateinit var mAdapter: RecyclerAdapter<Transaction>

override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   mAdapter = RecyclerAdapter(R.layout.item_transaction)
}

fun updateTransactions() {
   mAdapter.notifyDataSetChanged()
}

Addition to @Benito Bertoli, 除了@Benito Bertoli之外,

the combination is actually unlike if-else 这个组合实际上与if-else不同

"test" ?. let {
    println ( "1. it=$it" )
} ?: let {
    println ( "2. it is null!" )
}

The result is: 结果是:

1. it=test

But if: 但如果:

"test" ?. let {
    println ( "1. it=$it" )
    null // finally returns null
} ?: let {
    println ( "2. it is null!" )
}

The result is: 结果是:

1. it=test
2. it is null!

Also, if use elvis first: 另外,如果先使用elvis:

null ?: let {
    println ( "1. it is null!" )
} ?. let {
    println ( "2. it=$it" )
}

The result is: 结果是:

1. it is null!
2. it=kotlin.Unit

Check useful methods out, it could be useful: 检查有用的方法,它可能是有用的:

/**
 * Performs [R] when [T] is not null. Block [R] will have context of [T]
 */
inline fun <T : Any, R> ifNotNull(input: T?, callback: (T) -> R): R? {
    return input?.let(callback)
}

/**
 * Checking if [T] is not `null` and if its function completes or satisfies to some condition.
 */
inline fun <T: Any> T?.isNotNullAndSatisfies(check: T.() -> Boolean?): Boolean{
    return ifNotNull(this) { it.run(check) } ?: false
}

Below is possible example how to use those functions: 以下是如何使用这些功能的可能示例:

var s: String? = null

// ...

if (s.isNotNullAndSatisfies{ isEmpty() }{
   // do something
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM