วิธีที่ดีที่สุดในการตรวจสอบค่าว่างใน Kotlin?


98

ฉันควรใช้ double =หรือ triple =?

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

หรือ

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

ในทำนองเดียวกันสำหรับ 'not equals':

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

หรือ

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

1
ดูลิงค์: - kotlinlang.org/docs/reference/null-safety.html .............. ง่ายๆใน Kotlin Docs
sushildlh

คำตอบ:


63

ทั้งสองวิธีสร้าง bytecode เดียวกันเพื่อให้คุณสามารถเลือกอะไรก็ได้ที่คุณต้องการ


4
ถ้าฉันเข้าใจอย่างถูกต้องเขาก็กำลังขอวิธีที่ดีที่สุดในการตรวจสอบ null ใน Kotlin ไม่ใช่ว่าวิธีใดที่สร้างรหัสไบต์ที่ดีที่สุดคำตอบของ @BenitoBertoli ดูมีแนวโน้มจะลดรหัสสำเร็จรูป
imGs

156

ความเท่าเทียมกันของโครงสร้างa == bถูกแปลเป็น

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

ดังนั้นเมื่อเทียบกับnullที่เท่าเทียมกันของโครงสร้างจะแปลให้สมการอ้างอิงa == nulla === null

ตามเอกสารไม่มีจุดใดในการเพิ่มประสิทธิภาพโค้ดของคุณดังนั้นคุณสามารถใช้a == nullและa != null


โปรดทราบว่าหากตัวแปรเป็นคุณสมบัติที่ไม่แน่นอนคุณจะไม่สามารถส่งสมาร์ทให้เป็นประเภทที่ไม่เป็นโมฆะได้ภายในifคำสั่ง (เนื่องจาก ค่าอาจถูกแก้ไขโดยเธรดอื่น) และคุณต้องใช้ตัวดำเนินการโทรปลอดภัยletแทน

ผู้ให้บริการโทรปลอดภัย ?.

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


คุณสามารถใช้ร่วมกับตัวดำเนินการเอลวิสได้

ผู้ดำเนินการเอลวิส?: (ฉันเดาว่าเพราะเครื่องหมายคำถามดูเหมือนผมของเอลวิส)

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

1
ทำไมคุณไม่ใช้ifสำหรับการตรวจสอบค่าว่าง a?.let{} ?: run{}มีความเหมาะสมเฉพาะในบางกรณีเท่านั้นมิฉะนั้นจะไม่ใช่สำนวน
voddan

2
@voddan ฉันไม่ได้แนะนำให้ไม่ใช้ if สำหรับnullเช็คฉันกำลังแสดงรายการตัวเลือกอื่น ๆ ที่เป็นไปได้ แม้ว่าฉันจะไม่แน่ใจว่าrunมีโทษด้านประสิทธิภาพหรือไม่ ฉันจะอัปเดตคำตอบเพื่อให้ชัดเจนยิ่งขึ้น
Benito Bertoli

1
@voddan ถ้าaเป็น a varให้ใช้การa?.let{} ?: run{}รับประกันว่าจะถูกผูกมัดอย่างถูกต้องในletขอบเขตทั้งหมด ถ้าaเป็นvalแล้วไม่มีความแตกต่าง
madeinqc

1
@madeinqc ถ้า a เป็นvalแล้วการใช้ let แตกต่างกันและมันก็แย่ ผมพบว่าบทความนี้ดีมากที่อธิบายมัน - Kotlin: ไม่เพียงแค่ใช้ LET สำหรับการตรวจสอบ
Sufian

39

Kotlin วิธีจัดการโมฆะ

การดำเนินการเข้าถึงที่ปลอดภัย

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ไม่แน่นอน ขอแนะนำให้ใช้คุณสมบัติอ่านอย่างเดียวให้มากที่สุดเท่าที่จะทำได้ซึ่งเป็นคุณสมบัติที่ปลอดภัยต่อเธรด

ใช้ 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 ของค่านี้ใช้เอลวิส
AjahnCharles

@AjahnCharles เข้าท่า))
Levon Petrosyan

1
นี่คือขยะภาษาใด ๆ ที่ทันสมัยสามารถจัดการกับตัวเลือกได้ดีกว่านี้ มันเป็นงานที่น่าเบื่อมากกว่าประโยชน์สำหรับโปรแกรมเมอร์
JBarros35

10

นอกเหนือจาก @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.