Devo usar duplo =
ou triplo =
?
if(a === null) {
//do something
}
ou
if(a == null) {
//do something
}
Da mesma forma para 'diferente de':
if(a !== null) {
//do something
}
ou
if(a != null) {
//do something
}
Devo usar duplo =
ou triplo =
?
if(a === null) {
//do something
}
ou
if(a == null) {
//do something
}
Da mesma forma para 'diferente de':
if(a !== null) {
//do something
}
ou
if(a != null) {
//do something
}
Respostas:
Ambas as abordagens geram o mesmo bytecode para que você possa escolher o que preferir.
Uma igualdade estrutural a == b
é traduzida em
a?.equals(b) ?: (b === null)
Portanto, ao comparar com null
, a igualdade estrutural a == null
é traduzida em uma igualdade referencial a === null
.
De acordo com os documentos , não há nenhum ponto em otimizar seu código, então você pode usar a == null
e a != null
Observe que se a variável for uma propriedade mutável, você não será capaz de fazer um smart cast para seu tipo não anulável dentro da if
instrução (porque o valor pode ter sido modificado por outro encadeamento) e você terá que usar o operador de chamada segura com let
.
Operadora de chamada segura ?.
a?.let {
// not null do something
println(it)
println("not null")
}
Você pode usá-lo em combinação com o operador Elvis.
Operador de Elvis ?:
(suponho que seja porque a marca de interrogatório se parece com o cabelo de Elvis)
a ?: println("null")
E se você deseja executar um bloco de código
a ?: run {
println("null")
println("The King has left the building")
}
Combinando os dois
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
para verificações nulas? a?.let{} ?: run{}
só é apropriado em casos raros, caso contrário, não é idiomático
null
cheques, eu estava listando outras opções viáveis. Embora eu não tenha certeza se run
tem algum tipo de penalidade de desempenho. Vou atualizar minha resposta para torná-la mais clara.
a
for um var
, use a a?.let{} ?: run{}
garantia de que será vinculado corretamente no let
para todo o escopo. Se a
for um val
, então não há diferença.
val
, então usar let é diferente e é ruim. Achei este artigo muito bom em explicar isso - Kotlin: Não use LET apenas para verificação de nulos .
Operação de acesso seguro
val dialog : Dialog? = Dialog()
dialog?.dismiss() // if the dialog will be null,the dismiss call will be omitted
Deixe funcionar
user?.let {
//Work with non-null user
handleNonNullUser(user)
}
Saída antecipada
fun handleUser(user : User?) {
user ?: return //exit the function if user is null
//Now the compiler knows user is non-null
}
Sombras imutáveis
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
}
Valor padrão
fun getUserName(): String {
//If our nullable reference is not null, use it, otherwise use non-null value
return userName ?: "Anonymous"
}
Use val em vez de var
val
é somente leitura, var
é mutável. Recomenda-se usar tantas propriedades somente leitura quanto possível, elas são thread-safe.
Use lateinit
Às vezes, você não pode usar propriedades imutáveis. Por exemplo, isso acontece no Android quando alguma propriedade é inicializada na onCreate()
chamada. Para essas situações, o Kotlin possui um recurso de linguagem chamado 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()
}
Adição a @Benito Bertoli,
a combinação é realmente diferente de if-else
"test" ?. let {
println ( "1. it=$it" )
} ?: let {
println ( "2. it is null!" )
}
O resultado é:
1. it=test
Mas se:
"test" ?. let {
println ( "1. it=$it" )
null // finally returns null
} ?: let {
println ( "2. it is null!" )
}
O resultado é:
1. it=test
2. it is null!
Além disso, se usar o Elvis primeiro:
null ?: let {
println ( "1. it is null!" )
} ?. let {
println ( "2. it=$it" )
}
O resultado é:
1. it is null!
2. it=kotlin.Unit
Verifique métodos úteis, pode ser útil:
/**
* 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
}
Abaixo está um exemplo possível de como usar essas funções:
var s: String? = null
// ...
if (s.isNotNullAndSatisfies{ isEmpty() }{
// do something
}