在kotlin中检查无效的最佳方法?

pde*_*eva 67 kotlin kotlin-null-safety

我应该使用双倍=还是三倍=

if(a === null)  {
//do something
}
Run Code Online (Sandbox Code Playgroud)

要么

if(a == null)  {
//do something
}
Run Code Online (Sandbox Code Playgroud)

同样地,'不等于':

if(a !== null)  {
//do something
}
Run Code Online (Sandbox Code Playgroud)

要么

if(a != null)  {
//do something
}
Run Code Online (Sandbox Code Playgroud)

Ben*_*oli 100

结构平等a == b被转化为

a?.equals(b) ?: (b === null)
Run Code Online (Sandbox Code Playgroud)

因此,与之相比null,结构平等a == null被转化为指称平等a === null.

根据文档,优化代码是没有意义的,所以你可以使用a == nulla != null


注意,如果变量是一个可变属性,你将无法智能地将它转换为if语句中的非可空类型(因为该值可能已被另一个线程修改)并且您必须使用安全调用运算符let.

安全呼叫运营商 ?.

a?.let {
   // not null do something
   println(it)
   println("not null")
}
Run Code Online (Sandbox Code Playgroud)


您可以将它与Elvis运算符结合使用.

猫王操作员?: (我猜是因为审讯标记看起来像猫王的头发)

a ?: println("null")
Run Code Online (Sandbox Code Playgroud)

如果你想运行一段代码

a ?: run {
    println("null")
    println("The King has left the building")
}
Run Code Online (Sandbox Code Playgroud)

将两者结合起来

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")
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么不使用 `if` 进行空检查?`a?.let{} ?: run{}` 只适用于极少数情况,否则不符合习惯 (2认同)
  • @voddan我不是在建议不要使用null检查,而是列出其他可行的选择。尽管我不确定`run`是否会影响性能。我将更新答案以使其更加清晰。 (2认同)
  • @voddan 如果 `a` 是一个 `var`,那么使用 `a?.let{} ?: run{}` 保证它会在整个范围的 `let` 中正确绑定。如果`a` 是`val`,则没有区别。 (2认同)
  • @madeinqc 如果 a 是一个 `val`,那么使用 let 是不同的,而且它很糟糕。我发现这篇文章很好地解释了它 - [Kotlin:不要只使用 LET 进行 null 检查](https://medium.com/@elye.project/kotlin-dont-just-use-let-7e91f544e27f)。 (2认同)

Mic*_*ael 44

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

  • 如果我正确理解,那么他正在要求最好的方法来检查Kotlin中的null,而不是哪种方法会生成最佳的字节码。 (2认同)

Lev*_*yan 16

Kotlin处理null的方式

安全访问操作

val dialog : Dialog? = Dialog()
dialog?.dismiss()  // if the dialog will be null,the dismiss call will be omitted
Run Code Online (Sandbox Code Playgroud)

让功能

user?.let {
  //Work with non-null user
  handleNonNullUser(user)
}
Run Code Online (Sandbox Code Playgroud)

提前退出

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

不变的阴影

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
}
Run Code Online (Sandbox Code Playgroud)

默认值

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

使用val而不是var

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

使用lateinit

Sometimes you can’t use immutable properties. For example, it happens on Android when some property is initialized in onCreate() call. For these situations, Kotlin has a language feature called 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()
}
Run Code Online (Sandbox Code Playgroud)


Vla*_*lad 5

检查出有用的方法,这可能是有用的:

/**
 * 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
}
Run Code Online (Sandbox Code Playgroud)

下面是如何使用这些功能的可能示例:

var s: String? = null

// ...

if (s.isNotNullAndSatisfies{ isEmpty() }{
   // do something
}
Run Code Online (Sandbox Code Playgroud)


Bin*_*224 5

除了@Benito Bertoli,

组合实际上不同于if-else

"test" ?. let {
    println ( "1. it=$it" )
} ?: let {
    println ( "2. it is null!" )
}
Run Code Online (Sandbox Code Playgroud)

结果是:

1. it=test
Run Code Online (Sandbox Code Playgroud)

但是如果:

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

结果是:

1. it=test
2. it is null!
Run Code Online (Sandbox Code Playgroud)

另外,如果首先使用Elvis:

null ?: let {
    println ( "1. it is null!" )
} ?. let {
    println ( "2. it=$it" )
}
Run Code Online (Sandbox Code Playgroud)

结果是:

1. it is null!
2. it=kotlin.Unit
Run Code Online (Sandbox Code Playgroud)