Powinienem użyć podwójnego =
czy potrójnego =
?
if(a === null) {
//do something
}
lub
if(a == null) {
//do something
}
Podobnie dla „nie równa się”:
if(a !== null) {
//do something
}
lub
if(a != null) {
//do something
}
kotlin
kotlin-null-safety
pdeva
źródło
źródło
Odpowiedzi:
Obie metody generują ten sam kod bajtowy, więc możesz wybrać, co wolisz.
źródło
Równość strukturalna
a == b
jest tłumaczona naa?.equals(b) ?: (b === null)
Dlatego w porównaniu
null
z równością strukturalnąa == null
przekłada się na równość referencyjnąa === null
.Zgodnie z dokumentacją nie ma sensu optymalizowanie kodu, więc możesz użyć
a == null
ia != null
Zauważ, że jeśli zmienna jest zmienną właściwością, nie będziesz w stanie inteligentnie rzutować jej na jej typ, który nie dopuszcza wartości null w
if
instrukcji (ponieważ wartość mogła zostać zmodyfikowana przez inny wątek) ilet
zamiast tego musiałbyś użyć bezpiecznego operatora wywołania .Bezpieczny operator połączeń
?.
a?.let { // not null do something println(it) println("not null") }
Możesz go używać w połączeniu z operatorem Elvisa.
Operator Elvisa
?:
(zgaduję, ponieważ znak przesłuchania wygląda jak włosy Elvisa)a ?: println("null")
A jeśli chcesz uruchomić blok kodu
a ?: run { println("null") println("The King has left the building") }
Połączenie tych dwóch
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") }
źródło
if
do sprawdzania wartości zerowej?a?.let{} ?: run{}
jest właściwe tylko w rzadkich przypadkach, w przeciwnym razie nie jest idiomatycznenull
kontroli, wymieniłem inne możliwe opcje. Chociaż nie jestem pewien, czyrun
ma jakiś rodzaj spadku wydajności. Zaktualizuję odpowiedź, aby była bardziej przejrzysta.a
jest avar
, to korzystając za?.let{} ?: run{}
gwarancji, że zostanie on poprawnie powiązany wlet
całym zakresie. Jeślia
jestval
, to nie ma różnicy.val
, to użycie let jest inne i złe. Uważam, że ten artykuł jest bardzo dobry w wyjaśnianiu tego - Kotlin: Nie używaj LET tylko do sprawdzenia zerowego .Kotlin sposoby obsługi null
Bezpieczna operacja dostępu
val dialog : Dialog? = Dialog() dialog?.dismiss() // if the dialog will be null,the dismiss call will be omitted
Niech funkcjonuje
user?.let { //Work with non-null user handleNonNullUser(user) }
Wczesne wyjście
fun handleUser(user : User?) { user ?: return //exit the function if user is null //Now the compiler knows user is non-null }
Niezmienne cienie
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 }
Domyślna wartość
fun getUserName(): String { //If our nullable reference is not null, use it, otherwise use non-null value return userName ?: "Anonymous" }
Użyj val zamiast var
val
jest tylko do odczytu,var
jest zmienny. Zaleca się używanie jak największej liczby właściwości tylko do odczytu, są one bezpieczne dla wątków.Użyj lateinit
Czasami nie można użyć niezmiennych właściwości. Na przykład dzieje się tak w systemie Android, gdy w
onCreate()
wywołaniu inicjowana jest jakaś właściwość . W takich sytuacjach Kotlin ma funkcję języka o nazwielateinit
.private lateinit var mAdapter: RecyclerAdapter<Transaction> override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mAdapter = RecyclerAdapter(R.layout.item_transaction) } fun updateTransactions() { mAdapter.notifyDataSetChanged() }
źródło
Dodatek do @Benito Bertoli,
kombinacja jest w rzeczywistości odmienna od if-else
"test" ?. let { println ( "1. it=$it" ) } ?: let { println ( "2. it is null!" ) }
Wynik to:
1. it=test
Ale jeśli:
"test" ?. let { println ( "1. it=$it" ) null // finally returns null } ?: let { println ( "2. it is null!" ) }
Wynik to:
1. it=test 2. it is null!
Ponadto, jeśli najpierw użyjesz elvisa:
null ?: let { println ( "1. it is null!" ) } ?. let { println ( "2. it=$it" ) }
Wynik to:
1. it is null! 2. it=kotlin.Unit
źródło
Sprawdź przydatne metody, może się przydać:
/** * 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 }
Poniżej możliwy przykład wykorzystania tych funkcji:
var s: String? = null // ... if (s.isNotNullAndSatisfies{ isEmpty() }{ // do something }
źródło