在 Kotlin 检查无效的最好方法?

我应该使用双 =还是三 =

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

或者

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

对于“不等于”也是如此:

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

或者

if(a != null)  {
//do something
}
181638 次浏览

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

结构相等 a == b被转换为

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

因此,当与 null比较时,结构等式 a == null被转换为引用等式 a === null

根据 医生,没有必要优化你的代码,所以你可以使用 a == nulla != null


注意 ,如果变量是一个可变属性,那么您将无法在 if语句中将其智能强制转换为它的非空类型(因为该值可能已被另一个线程修改) ,您必须使用 let的安全调用操作符。

安全呼叫操作员 ?.

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


你可以把它和猫王操作员结合起来使用。

埃尔维斯操作员 ?: < em > (我猜是因为问号看起来像埃尔维斯的头发)

a ?: println("null")

如果你想运行一段代码

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

把两者结合起来

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")
}

检查一下有用的方法,它可能是有用的:

/**
* 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
}

下面是如何使用这些函数的可能例子:

var s: String? = null


// ...


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

除了“贝尼托 · 贝托利”

这个组合实际上不像 if-else

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

结果是:

1. it=test

但如果:

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

结果是:

1. it=test
2. it is null!

此外,如果首先使用猫王:

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

结果是:

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

Kotlin 处理 null 的方法

安全访问操作

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

让功能

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

提前退场

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

永恒的影子

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
}

默认值

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

使用 val 而不是 var

val是只读的,var是可变的。建议使用尽可能多的只读属性,它们是线程安全的。

用乳胶

有时不能使用不可变属性。例如,在 Android 上,当某个属性在 onCreate()调用中初始化时,就会发生这种情况。对于这些情况,Kotlin 有一个名为 ABc1的语言特性。

private lateinit var mAdapter: RecyclerAdapter<Transaction>


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


fun updateTransactions() {
mAdapter.notifyDataSetChanged()
}

我想回答@Benito Bertoli 和@BingLi224的问题,并提供正确的解决方案。

问题在于使用 let,因为 let的结果是它的最后一个表达式。您只需要传递与传递给它的内容相同的内容,因此 also是一个更好的解决方案。同时,在使用了猫王操作符之后,let是不可能使用的,因为没有对象来调用扩展函数,所以我使用的是 run(函数版)。更多内容请看 正式文件

与使用 if/when相比,这样做的另一个缺点是不能将其用作表达式,因此我不推荐使用它: -)

最终代码:

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


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


null?.also {
println("1. it is null!")
} ?: run {
println("2. it is null")
}


null?.also {
println("1. it is null!")
null
} ?: run {
println("2. it is null")
}

输出:

1. it=test
1. it=test
2. it is null
2. it is null