Kotlinでnullチェックを行う最良の方法は?


94

ダブル=またはトリプルを使用する必要があります=か?

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

または

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

同様に「等しくない」の場合:

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

または

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

1
リンクを見てください:-kotlinlang.org/docs/reference/null-safety.html .............. Kotlin Docsで簡単
sushildlh

回答:


62

どちらのアプローチでも同じバイトコードが生成されるため、好きなものを選択できます。


2
。私はそれを正しく理解している場合、その後、彼はいないどのアプローチが最善のバイトコードを生成し、Kotlinのチェックnullに最善の方法を求めている@ BenitoBertoli回答ルックスは有望な、それはだが定型的なコードを削減
IMGS

148

構造的等価性a == b

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

したがって、と比較するnullと、構造的等価性a == nullは参照等価性に変換されますa === nullます。

よるとドキュメント、あなたが使用できるように、あなたのコードを最適化するにはポイントがありませんa == nulla != null


注意変数が変更可能なプロパティがある場合、あなたは内部のnull非許容型へのスマートキャスト、それをすることはできませんというif文は、(理由は値は別のスレッドによって変更されている可能性があります)let。代わりに、安全な呼び出し演算子を使用する必要があります。

安全な通話オペレーター ?.

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


Elvisオペレーターと組み合わせて使用​​できます。

エルビスオペレーター?: (尋問マークがエルビスの髪の毛のように見えるので、私は推測しています)

a ?: println("null")

そして、あなたがコードのブロックを実行したい場合

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

2つを組み合わせる

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

1
なぜifnullチェックに使用しないのですか?a?.let{} ?: run{}まれな場合にのみ適切ですが、それ以外は慣用的ではありません
voddan

2
@voddan nullチェックにifを使用しないことを提案していなかったので、他の実行可能なオプションをリストしていました。run何らかのパフォーマンスのペナルティがあるかどうかはわかりませんが。わかりやすくするために回答を更新します。
Benito Bertoli、2016年

1
@voddan If aがの場合、スコープ全体で正しくバインドされるvarというa?.let{} ?: run{}保証を使用しletます。場合avalは、違いはありません。
madeinqc

1
@madeinqc aがの場合、valletの使用は異なり、それは悪いことです。私はこの記事がそれを説明するのに非常に優れていると感じました-Kotlin:nullチェックにLETを使用しないでください
Sufian

34

nullを処理するKotlinの方法

安全なアクセス操作

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

Let関数

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

varの代わりにvalを使用する

val読み取り専用で、var変更可能です。スレッドセーフであるため、できるだけ多くの読み取り専用プロパティを使用することをお勧めします。

lateinitを使用する

不変のプロパティを使用できない場合があります。たとえば、Androidで一部のプロパティがonCreate()呼び出しで初期化されるときに発生します。これらの状況に対して、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()
}

そのうちの3/4はelvisを使用しているため、最後の1つを「デフォルト値」(elvisではない)と呼びます。
AjahnCharles

@AjahnCharlesは理にかなっています))
Levon Petrosyan

8

@Benito Bertoliへの追加、

組み合わせは実際には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!

また、最初にelvisを使用する場合:

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

結果は次のとおりです。

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

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
}

以下は、これらの関数の使用方法の例です。

var s: String? = null

// ...

if (s.isNotNullAndSatisfies{ isEmpty() }{
   // do something
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.