Storia della questione:
In Java, l'immutabilità delle collezioni viene raggiunta attraverso wrapper come Collections.unmodifiableList() e progettando classi immutabili manualmente (campi final, assenza di setter). Nella pratica dello sviluppo Android e server, questo diventava costoso e poco conveniente, e la sicurezza dei thread e la prevedibilità dei dati andavano perse.
Problema:
Le collezioni Java non sono sicure di default, è sempre possibile ottenere un riferimento e modificare l'oggetto. Ciò complica il controllo dell'immutabilità, specialmente in ambienti multi-thread, e porta a bug difficili da individuare.
Soluzione:
Kotlin è stato progettato sin dall'inizio con una separazione tra collezioni read-only e mutable, e la creazione di oggetti veramente immutabili è diventata più semplice grazie a val, data class e List/Set/Map senza il prefisso mutable. Su questo si basa — l'uso della copia tramite i metodi copy().
Esempio di codice:
val nums: List<Int> = listOf(1, 2, 3) // lista immutabile // nums.add(4) // errore di compilazione val user = User(name = "Alex", age = 30) val updated = user.copy(age = 31) // Esempio con una mappa immutabile val state: Map<String, Int> = mapOf("a" to 1, "b" to 2)
Caratteristiche chiave:
Val garantisce un'immutabilità assoluta dell'oggetto interno?
No! Val garantisce solo che la variabile non può riferirsi a un altro oggetto, ma i campi dell'oggetto possono essere modificati (se le proprietà interne sono var).
È possibile ottenere un oggetto mutabile da una collezione read-only?
Sì — se la collezione contiene un oggetto mutabile, è possibile modificare il suo stato, nonostante l'interfaccia read-only della collezione.
data class User(var name: String) val users: List<User> = listOf(User("Vasya")) users[0].name = "Petya" // consentito
Cosa accade quando si converte List<Int> in MutableList<Int> tramite as?
Si compila, ma genererà ClassCastException durante l'esecuzione se il tipo originale era un'interfaccia read-only.
Un'app Android memorizza lo stato in val List<User>, considerandola immutabile. Uno degli sviluppatori modifica user.name. In un'altra parte, la lista aggiornata mostra inaspettatamente dati non consistenti — il bug appare nella release.
Vantaggi:
Svantaggi:
Utilizzo di una data class immutabile solo con campi val, filtraggio dell'accesso agli oggetti annidati, aggiornamento dello stato tramite copy().
Vantaggi:
Svantaggi: