ProgrammazioneSviluppatore Android Middle

Come viene realizzata l'immutabilità delle collezioni e degli oggetti in Kotlin e in che modo la pratica si differisce da Java?

Supera i colloqui con l'assistente IA Hintsage

Risposta

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:

  • La compilazione tenterà di modificare una collezione read-only genererà un errore
  • In Kotlin val garantisce l'immutabilità del riferimento, ma non necessariamente dell'oggetto
  • Per oggetti davvero immutabili — utilizzare solo interfacce read-only e vietare la modifica dello stato interno

Domande trabocchetto.

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.

Errori tipici e anti-pattern

  • Considerare val come una garanzia assoluta di immutabilità dell'oggetto
  • Manipolazione di riferimenti a oggetti mutabili all'interno di collezioni "immutabili"
  • Conversione di collezioni read-only in collezioni mutabili

Esempio dalla vita reale

Caso negativo

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:

  • Rapido funzionamento con collezioni

Svantaggi:

  • Perdita di controllo sulle mutazioni
  • Immutabilità nascosta

Caso positivo

Utilizzo di una data class immutabile solo con campi val, filtraggio dell'accesso agli oggetti annidati, aggiornamento dello stato tramite copy().

Vantaggi:

  • Alta prevedibilità e sicurezza dei thread
  • Assenza di effetti collaterali imprevisti

Svantaggi:

  • A volte richiede più allocazioni e copie
  • Non tutte le librerie di terze parti offrono oggetti veramente immutabili