ตัวดำเนินการ Kotlin double-bang (!!) คืออะไร


177

ฉันกำลังแปลง Java เป็น Kotlin ด้วย Android Studio ฉันได้รับผลกระทบสองครั้งหลังจากตัวแปรอินสแตนซ์ Double Bang คืออะไรและที่สำคัญกว่านั้นเอกสารนี้คืออะไร

mMap!!.addMarker(MarkerOptions().position(london).title("Marker in London"))

คำตอบ:


205

นี้เป็นที่ไม่ปลอดภัยประเภท nullable ( T?แปลง) เป็นชนิดที่ไม่ใช่ nullable ( T) !!จะโยนถ้ามีค่าเป็นNullPointerExceptionnull

มันมีการบันทึกไว้ที่นี่พร้อมกับ Kotlin หมายถึงความปลอดภัยเป็นโมฆะ


1
หมายความว่าอย่างไรเมื่อ!!คำแถลงสิ้นสุด? IJ แปลงเป็น Kotlin ให้ฉันโดยอัตโนมัติval price = sale.latest!!
ycomp

7
@ycomp หมายความว่าsale.latestสามารถมีได้null; การมอบหมายจะสำเร็จก็ต่อเมื่อsale.latestไม่ใช่โมฆะและจะโยน NPE เป็นอย่างอื่น สิ่งนี้ให้ความปลอดภัยเป็นโมฆะสำหรับval price: ประเภทของมันจะไม่เป็นโมฆะ ดูkotlinlang.org/docs/reference/null-safety.html
ฮอต

1
@hotkey: แล้วอะไรคือความแตกต่างระหว่างการรับ NPE - ที่นี่หรือเมื่อเข้าถึงวิธีล่าสุดบนวัตถุ null?
Aada

2
@Aada เป็นปัญหาที่พบได้บ่อยในการดีบัก NPE และมีปัญหาในการค้นหาเส้นทางบรรทัด / การดำเนินการที่ตั้งค่าเป็นศูนย์ การกำหนดค่าว่างนี้อาจเกิดขึ้นในบริบทชั้นเรียนหรือแม้แต่วันอื่น! โดยการใช้!!คุณสามารถล้มเหลวอย่างรวดเร็วและค้นหาสาเหตุของ NPE ฉันหวังว่า Java มีคุณสมบัติที่คล้ายกัน (นั่นคือifคำสั่งw / o น่าเกลียดและ / หรือassertไอออน)
Cascader

82

นี่คือตัวอย่างเพื่อทำให้สิ่งต่าง ๆ ชัดเจนขึ้น สมมติว่าคุณมีฟังก์ชั่นนี้

fun main(args: Array<String>) {
    var email: String
    email = null
    println(email)
}

สิ่งนี้จะสร้างข้อผิดพลาดในการรวบรวมดังต่อไปนี้

Null can not be a value of a non-null type String

ตอนนี้คุณสามารถป้องกันได้โดยเพิ่มเครื่องหมายคำถามลงในStringประเภทเพื่อทำให้เป็นโมฆะ

ดังนั้นเราจึงมี

fun main(args: Array<String>) {
    var email: String?
    email = null
    println(email)
}

สิ่งนี้ก่อให้เกิดผล

null

ตอนนี้ถ้าเราต้องการให้ฟังก์ชันส่งข้อยกเว้นเมื่อค่าของอีเมลเป็นโมฆะเราสามารถเพิ่มอัศเจรีย์สองตัวที่ส่วนท้ายของอีเมล แบบนี้

fun main(args: Array<String>) {
    var email: String?
    email = null
    println(email!!)
}

นี่จะเป็นการโยน KotlinNullPointerException


5
ดังนั้นทำไมคนจะใช้ '!!' ถึงแม้ว่ามันจะไม่ปลอดภัยเพราะแอพจะถูกยกเลิกเมื่อตัวแปรนั้นมีค่าว่าง?
Sam

3
@david คุณสามารถใช้ได้เฉพาะเมื่อคุณแน่ใจ 100% ว่าตัวแปรไม่เป็นโมฆะ (เช่นคุณตรวจสอบอย่างชัดเจน) และคุณต้องการตัวแปรที่ไม่สามารถลบล้างได้
FMK

7
@FMK ฉันเข้าใจแล้วขอบคุณ! ฉันเข้าใจว่า double bang ถูกใช้เพื่อทำให้เป็นไปได้ว่าค่าของตัวแปรชนิด nullable ไปเป็นตัวแปรชนิด non-nullable ใช่ไหม?
แซม

2
@ David ใช่แน่นอน
FMK

10

ตัวดำเนินการ Double-bangเป็นตัวเลือกที่ยอดเยี่ยมสำหรับแฟน ๆ ของNullPointerException(หรือ NPE สำหรับระยะสั้น)

ผู้ประกอบการยืนยันไม่ null !!แปลงค่าใด ๆ ไปไม่ใช่ประเภท nullและพ่นยกเว้นถ้าค่าเป็นโมฆะ

val nonNull = a!!.length

ดังนั้นคุณสามารถเขียนa!!และสิ่งนี้จะส่งกลับค่าที่ไม่ใช่aศูนย์ ( Stringเช่นที่นี่) หรือโยน NPE ถ้าaเป็นโมฆะ

หากคุณต้องการ NPE คุณสามารถรับได้ แต่คุณต้องขออย่างชัดเจน ผู้ประกอบการนี้ควรจะใช้ในกรณีที่มีนักพัฒนาที่มีการรับประกัน - ค่าจะไม่เป็นโมฆะ


2
ถามเป็นผู้เริ่มต้น: ทำไมฉันต้องการแปลงค่าใด ๆ ให้เป็นประเภทที่ไม่ใช่ค่าว่าง?
Wolf359

4
@ Wolf359 มันช่วยให้คุณมั่นใจได้ 100% ว่าค่าไม่เป็นโมฆะ ("เป็นปัญหาทั่วไปในการดีบัก NPE และมีปัญหาในการค้นหาเส้นทาง / การดำเนินการที่ตั้งค่าเป็น null การกำหนดค่า Null นี้อาจเกิดขึ้นในบริบทชั้นเรียนหรือแม้แต่วันอื่น!" โดย Cascader)
กิจกรรมลด
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.