Qual a diferença entre val e var em Kotlin?
Essa é uma das primeiras coisas que você aprende em Kotlin, e entender direitinho a diferença entre val e var vai te poupar muita dor de cabeça. Vamos lá!
A explicação rápida
val(de value): declara uma variável imutável. Depois que você atribui um valor, não pode mais mudar.var(de variable): declara uma variável mutável. Você pode alterar o valor quantas vezes quiser.
Pense assim: val é como escrever a caneta, e var é como escrever a lápis.
Se você quer se aprofundar nesses conceitos, temos páginas dedicadas no glossário para val e var, além de um tutorial completo sobre variáveis e tipos em Kotlin.
Na prática
fun main() {
// val - imutável: uma vez atribuído, não muda
val nome = "Karina"
// nome = "Ana" // ERRO! Não pode reatribuir um val
// var - mutável: pode mudar à vontade
var pontuacao = 0
println("Pontuação inicial: $pontuacao")
pontuacao = 10
println("Pontuação atualizada: $pontuacao")
pontuacao += 5
println("Pontuação final: $pontuacao")
}
Se você tentar reatribuir um val, o compilador vai reclamar na hora com um erro bem claro. Isso é uma mão na roda pra evitar bugs.
Quando usar cada um?
A regra de ouro é: prefira sempre val. Use var somente quando realmente precisar alterar o valor depois.
Por que? Variáveis imutáveis tornam o código mais previsível e seguro. Quando você sabe que um valor não vai mudar, fica muito mais fácil entender o que o código está fazendo.
fun main() {
// Boas práticas
val cpf = "123.456.789-00" // CPF não muda, usa val
val dataNascimento = "15/03/1995" // data de nascimento não muda, usa val
var saldo = 1000.0 // saldo muda, usa var
saldo -= 150.0 // compra no débito
println("Saldo atual: R$ $saldo")
}
Cuidado: val não significa objeto imutável
Um detalhe que pega muita gente: val impede a reatribuição, mas não impede a modificação interna do objeto. Veja:
fun main() {
val frutas = mutableListOf("Banana", "Maçã", "Manga")
// Isso funciona! Estamos modificando a lista, não reatribuindo a variável
frutas.add("Abacaxi")
println(frutas) // [Banana, Maçã, Manga, Abacaxi]
// Isso NÃO funciona! Estamos tentando reatribuir
// frutas = mutableListOf("Uva") // ERRO!
}
Se quiser uma lista que não pode ser modificada de jeito nenhum, use listOf() em vez de mutableListOf(). Para entender melhor as diferenças entre coleções mutáveis e imutáveis, confira nosso conteúdo sobre collections e o tutorial de coleções em Kotlin.
Erros comuns de quem está começando
Vamos ver alguns erros que aparecem com frequência e como evitá-los:
1. Usar var quando val resolveria
// Ruim: var desnecessário
var mensagem = "Bem-vindo ao sistema"
println(mensagem)
// Bom: se não vai mudar, use val
val mensagem = "Bem-vindo ao sistema"
println(mensagem)
O IntelliJ IDEA e o Android Studio inclusive exibem um aviso quando você declara um var que nunca é reatribuído, sugerindo trocar para val.
2. Confundir imutabilidade da referência com imutabilidade do conteúdo
fun main() {
val numeros = mutableListOf(1, 2, 3)
numeros.add(4) // Funciona: estamos alterando o conteúdo
// numeros = mutableListOf(5) // ERRO: estamos tentando reatribuir a referência
// Para imutabilidade total, combine val com coleção imutável
val numerosFixos = listOf(1, 2, 3)
// numerosFixos.add(4) // ERRO: listOf() não tem método add
}
3. Esquecer que val funciona diferente em classes
Dentro de uma classe, val define uma propriedade somente leitura, enquanto var define uma propriedade que pode ser alterada:
class ContaBancaria(val titular: String, var saldo: Double) {
fun depositar(valor: Double) {
saldo += valor // OK: saldo é var
}
// titular não pode ser alterado depois da criação
}
fun main() {
val conta = ContaBancaria("Maria", 500.0)
conta.depositar(200.0)
println("Saldo: ${conta.saldo}") // 700.0
// conta.titular = "Joao" // ERRO! titular é val
}
val e var em funções
Parâmetros de funções em Kotlin são sempre imutáveis (equivalentes a val). Você não pode reatribuir um parâmetro dentro do corpo da função:
fun calcularDesconto(preco: Double, percentual: Double): Double {
// preco = preco * 0.9 // ERRO! Parâmetros são imutáveis
val precoComDesconto = preco * (1 - percentual / 100)
return precoComDesconto
}
Essa decisão de design foi intencional. Ela evita efeitos colaterais confusos e torna o código mais previsível. Se você vem do Java, onde parâmetros podem ser reatribuídos, vai notar essa diferença logo de cara.
val e var com delegação de propriedades
Kotlin tem um recurso avançado chamado delegação de propriedades que funciona tanto com val quanto com var. O exemplo mais conhecido é o lazy, que só inicializa o valor quando ele é acessado pela primeira vez:
val configuracao: Map<String, String> by lazy {
println("Carregando configuração...")
mapOf("tema" to "escuro", "idioma" to "pt-BR")
}
fun main() {
println("Antes de acessar")
println(configuracao["tema"]) // Só aqui o bloco lazy é executado
}
Para saber mais sobre esse recurso, veja nosso glossário sobre property delegate.
Resumindo
| Aspecto | val | var |
|---|---|---|
| Reatribuição | Não permite | Permite |
| Equivalente em Java | final | variável comum |
| Quando usar | Sempre que possível | Quando precisar mudar o valor |
| Parâmetros de função | Comportamento padrão | Não disponível |
| Performance | Pode ser otimizado pelo compilador | Sem otimizações extras |
Adotar o hábito de usar val por padrão é uma das melhores práticas em Kotlin. Seu código fica mais limpo, mais seguro e mais fácil de manter. Na dúvida, comece com val e só troque pra var se o compilador reclamar que você está tentando alterar o valor.
Se você quer continuar aprendendo sobre os fundamentos da linguagem, confira nosso guia completo de Kotlin e o tutorial sobre funções em Kotlin. Para entender o conceito mais amplo de imutabilidade e por que ele é tão importante na programação moderna, temos um artigo dedicado no glossário.