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
}
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
}
Odpowiedzi:
Obie metody generują ten sam kod bajtowy, więc możesz wybrać, co wolisz.
Równość strukturalna a == b
jest tłumaczona na
a?.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
i a != 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) i let
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")
}
if
do sprawdzania wartości zerowej? a?.let{} ?: run{}
jest właściwe tylko w rzadkich przypadkach, w przeciwnym razie nie jest idiomatyczne
null
kontroli, wymieniłem inne możliwe opcje. Chociaż nie jestem pewien, czy run
ma jakiś rodzaj spadku wydajności. Zaktualizuję odpowiedź, aby była bardziej przejrzysta.
a
jest a var
, to korzystając z a?.let{} ?: run{}
gwarancji, że zostanie on poprawnie powiązany w let
całym zakresie. Jeśli a
jest val
, 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 .
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 nazwie 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()
}
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
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
}