Cara terbaik untuk mengecek nol di Kotlin?

98

Haruskah saya menggunakan double =, atau triple= ?

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

atau

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

Demikian pula untuk 'tidak sama dengan':

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

atau

if(a != null)  {
//do something
}
pdeva
sumber
1
lihat di link: - kotlinlang.org/docs/reference/null-safety.html .............. Mudah di Kotlin Docs
sushildlh

Jawaban:

63

Kedua pendekatan tersebut menghasilkan bytecode yang sama sehingga Anda dapat memilih apa pun yang Anda inginkan.

Michael
sumber
4
Jika saya memahaminya dengan benar maka dia meminta cara terbaik untuk memeriksa null di Kotlin, bukan pendekatan mana yang menghasilkan kode byte terbaik. @ Jawaban BenitoBertoli tampak menjanjikan, ini mengurangi kode boilerplate
imGs
156

Kesetaraan struktural a == bditerjemahkan ke

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

Oleh karena itu, bila dibandingkan dengan null, persamaan struktural a == nullditerjemahkan menjadi persamaan referensial a === null.

Menurut dokumen , tidak ada gunanya mengoptimalkan kode Anda, jadi Anda dapat menggunakan a == nulldan a != null


Perhatikan bahwa jika variabel adalah properti yang bisa berubah, Anda tidak akan bisa mentransmisikannya ke tipe non-nullable di dalam ifpernyataan (karena nilainya mungkin telah dimodifikasi oleh utas lain) dan Anda harus menggunakan operator panggilan aman denganlet sebagai gantinya.

Operator panggilan aman ?.

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


Anda dapat menggunakannya bersama operator Elvis.

Operator Elvis ?: (Saya menebak karena tanda interogasi terlihat seperti rambut Elvis)

a ?: println("null")

Dan jika Anda ingin menjalankan blok kode

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

Menggabungkan keduanya

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")
}
Benito Bertoli
sumber
1
mengapa Anda tidak menggunakan ifuntuk pemeriksaan nol? a?.let{} ?: run{}hanya sesuai dalam kasus yang jarang terjadi, jika tidak maka tidak idiomatis
voddan
2
@voddan Saya tidak menyarankan untuk tidak menggunakan jika untuk nullpemeriksaan, saya mencantumkan opsi lain yang layak. Meskipun saya tidak yakin apakah runmemiliki semacam penalti kinerja. Saya akan memperbarui jawaban saya untuk membuatnya lebih jelas.
Benito Bertoli
1
@voddan Jika aadalah a var, maka gunakan a?.let{} ?: run{}jaminan bahwa itu akan terikat dengan benar di letuntuk seluruh ruang lingkup. Jika aa val, maka tidak ada perbedaan.
dibuat
1
@madeinqc jika a val, maka menggunakan let berbeda dan itu buruk. Saya menemukan artikel ini sangat bagus dalam menjelaskannya - Kotlin: Jangan hanya menggunakan LET untuk pemeriksaan null .
Sufian
40

Cara Kotlin menangani null

Operasi Akses Aman

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

Biarkan berfungsi

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

Keluar lebih awal

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

Bayangan yang tidak bisa diubah

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
}

Nilai default

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

Gunakan val, bukan var

valbersifat read-only, varbisa berubah. Direkomendasikan untuk menggunakan sebanyak mungkin properti hanya-baca, properti ini aman untuk thread.

Gunakan lateinit

Terkadang Anda tidak dapat menggunakan properti yang tidak dapat diubah. Misalnya, ini terjadi di Android ketika beberapa properti diinisialisasi dalam onCreate()panggilan. Untuk situasi ini, Kotlin memiliki fitur bahasa yang disebut 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()
}
Levon Petrosyan
sumber
Saya akan menyebut yang terakhir sebagai "nilai default" (bukan elvis), karena 3/4 di antaranya menggunakan elvis.
AjahnCharles
@AjahnCharles masuk akal))
Levon Petrosyan
1
ini sampah, bahasa modern apa pun dapat menangani lebih baik dengan pilihan daripada ini. itu lebih merupakan tugas daripada manfaat bagi programmer.
JBarros35
10

Selain @Benito Bertoli,

kombinasinya sebenarnya tidak seperti if-else

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

Hasilnya adalah:

1. it=test

Tapi jika:

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

Hasilnya adalah:

1. it=test
2. it is null!

Juga, jika menggunakan elvis dulu:

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

Hasilnya adalah:

1. it is null!
2. it=kotlin.Unit
BingLi224
sumber
5

Lihat metode yang berguna, ini bisa berguna:

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

Di bawah ini adalah contoh yang mungkin bagaimana menggunakan fungsi tersebut:

var s: String? = null

// ...

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