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 == bjest tłumaczona na
a?.equals(b) ?: (b === null)
Dlatego w porównaniu nullz równością strukturalną a == nullprzekłada się na równość referencyjną a === null.
Zgodnie z dokumentacją nie ma sensu optymalizowanie kodu, więc możesz użyć a == nulli 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 ifinstrukcji (ponieważ wartość mogła zostać zmodyfikowana przez inny wątek) i letzamiast 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")
}
ifdo sprawdzania wartości zerowej? a?.let{} ?: run{}jest właściwe tylko w rzadkich przypadkach, w przeciwnym razie nie jest idiomatyczne
nullkontroli, wymieniłem inne możliwe opcje. Chociaż nie jestem pewien, czy runma jakiś rodzaj spadku wydajności. Zaktualizuję odpowiedź, aby była bardziej przejrzysta.
ajest a var, to korzystając z a?.let{} ?: run{}gwarancji, że zostanie on poprawnie powiązany w letcałym zakresie. Jeśli ajest 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
valjest tylko do odczytu, varjest 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
}