Panduan Komprehensif untuk Keselamatan Null di Kotlin

1. Gambaran keseluruhan

Dalam artikel ini, kita akan melihat ciri keselamatan nol yang terdapat dalam bahasa Kotlin. Kotlin memberikan penanganan yang lengkap dan asli dari bidang yang tidak dapat ditarik - tidak perlu perpustakaan tambahan.

2. Ketergantungan Maven

Untuk memulakan, anda perlu menambahkan pergantungan kotlin-stdlib Maven ke pom.xml anda :

 org.jetbrains.kotlin kotlin-stdlib 1.1.1  

Anda boleh mendapatkan versi terbaru di Maven Central.

3. Jenis Rujukan Tidak Boleh Dihapus dan Tidak Boleh Ditolak

Kotlin mempunyai dua jenis rujukan yang ditafsirkan oleh penyusun untuk memberi maklumat kepada pengaturcara mengenai kebenaran sesuatu program pada waktu kompilasi - yang tidak dapat dibatalkan dan yang tidak.

Secara lalai, Kotlin menganggap bahawa nilai tidak boleh nol :

var a: String = "value" assertEquals(a.length, 5)

Kami tidak dapat memberikan nol pada rujukan a , dan jika anda mencuba, ini akan menyebabkan ralat penyusun.

Sekiranya kita ingin membuat rujukan yang tidak dapat ditolak, kita perlu membuat tambahkan tanda tanya (?) Pada definisi jenis :

var b: String? = "value"

Selepas itu, kami dapat memberikannya nol :

b = null

Apabila kita ingin mengakses rujukan b , kita mesti menangani kes nol secara eksplisit untuk mengelakkan ralat penyusunan kerana Kotlin tahu bahawa pemboleh ubah ini dapat menahan nol :

if (b != null) { println(b.length) } else { assertNull(b) }

4. Panggilan Selamat

Menangani setiap rujukan yang tidak dapat ditolerir dengan cara sedemikian dapat membebani. Nasib baik, Kotlin mempunyai sintaks untuk "panggilan selamat" - sintaks ini membolehkan pengaturcara untuk melakukan tindakan hanya apabila rujukan khusus memegang nilai tidak nol .

Mari kita tentukan dua kelas data untuk menggambarkan ciri ini:

data class Person(val country: Country?) data class Country(val code: String?)

Perhatikan bahawa medan negara dan kod adalah jenis rujukan yang tidak dapat ditolak.

Untuk mengakses bidang tersebut dengan lancar, kita dapat menggunakan sintaks panggilan selamat:

val p: Person? = Person(Country("ENG")) val res = p?.country?.code assertEquals(res, "ENG")

Sekiranya pemboleh ubah p menahan nol , sintaks panggilan selamat akan mengembalikan hasil nol :

val p: Person? = Person(Country(null)) val res = p?.country?.code assertNull(res)

4.1. Kaedah let ()

Untuk melaksanakan tindakan hanya apabila rujukan memiliki nilai yang tidak dapat ditolak, kita dapat menggunakan operator let .

Katakan bahawa kita mempunyai senarai nilai dan ada juga nilai nol dalam senarai itu:

val firstName = "Tom" val secondName = "Michael" val names: List = listOf(firstName, null, secondName)

Seterusnya, kita dapat melakukan tindakan pada setiap elemen daftar nama yang tidak dapat dibatalkan dengan menggunakan fungsi let :

var res = listOf() for (item in names) { item?.let { res = res.plus(it) } } assertEquals(2, res.size) assertTrue { res.contains(firstName) } assertTrue { res.contains(secondName) }

4.2. Kaedah juga ()

Sekiranya kita ingin menerapkan beberapa operasi tambahan, misalnya log masuk pada setiap nilai yang tidak dapat ditolak, kita boleh menggunakan kaedah juga () dan mengaitkannya dengan let ():

var res = listOf() for (item in names) { item?.let { res = res.plus(it); it } ?.also{it -> println("non nullable value: $it")} }

Ia akan mencetak setiap elemen yang tidak kosong:

non nullable value: Tom non nullable value: Michael

4.3. Kaedah larian ()

Kotlin mempunyai kaedah run () untuk menjalankan beberapa operasi pada rujukan yang tidak dapat dibatalkan. Ini sangat mirip dengan let () tetapi di dalam badan fungsi, Kaedah Run () beroperasi pada rujukan ini dan bukannya parameter fungsi:

var res = listOf() for (item in names) { item?.run{res = res.plus(this)} }

5. Pengendali Elvis

Kadang-kadang, apabila kita mempunyai rujukan, kita mahu kembali beberapa nilai lalai dari operasi jika rujukan memegang null . Untuk mencapainya, kita boleh menggunakan operator elvis ( ? :) . Ini adalah setara dengan orElse / orElseGet dari kelas Java Pilihan :

val value: String? = null val res = value?.length ?: -1 assertEquals(res, -1)

Apabila rujukan nilai memegang nilai yang tidak dapat ditolak, panjang kaedah akan dipanggil:

val value: String? = "name" val res = value?.length ?: -1 assertEquals(res, 4)

6. Dapatkan Tidak Selamat yang Boleh Dibatalkan

Kotlin also has an unsafe operator to get a value of a nullable field without handling absence logic explicitly, but it should be used very carefully.

The double exclamation mark operator (!!) takes a value from a nullable reference and throws a NullPointerException if it holds null. This is an equivalent of Optional.get() operation:

var b: String? = "value" b = null assertFailsWith { b!! }

If the nullable reference holds a non-nullable value, the action on that value will be executed successfully:

val b: String? = "value" assertEquals(b!!.length, 5)

7. Filtering Null Values From a List

The List class in Kotlin has a utility method filterNotNull() that returns only non-nullable values from a list that holds nullable references:

val list: List = listOf("a", null, "b") val res = list.filterNotNull() assertEquals(res.size, 2) assertTrue { res.contains("a") } assertTrue { res.contains("b") }

Ini adalah konstruk yang sangat berguna yang merangkumi logik yang sebaliknya perlu kita laksanakan sendiri.

8. Kesimpulannya

Dalam artikel ini, kami menerokai ciri keselamatan nol Koltin secara mendalam. Kami melihat jenis rujukan yang dapat menyimpan nilai nol dan yang tidak dapat. Kami menerapkan logik pengendalian nol lancar dengan menggunakan ciri "panggilan selamat" dan operator elvis .

Pelaksanaan semua contoh dan coretan kod ini terdapat dalam projek GitHub - ini adalah projek Maven, jadi mudah untuk diimport dan dijalankan sebagaimana adanya.