Tag: kotlin, jvm, android, coroutines, null-safety, oop
Livello: intermedio
TL;DR: Linguaggio a tipizzazione statica per la JVM, conciso e sicuro, focalizzato sull'eliminazione delle NullPointerException e sull'interoperabilità completa con Java.
Null safety nativa: il type system distingue rigorosamente i tipi nullable (Type?) da quelli non-nullable (Type).
Immutabilità di default: val definisce variabili in sola lettura, var definisce variabili mutabili.
Smart casts: il compilatore effettua il cast automatico del tipo subito dopo averlo verificato con l'operatore is.
Data classes: generano in automatico equals(), hashCode(), toString() e copy() per i modelli di dati senza boilerplate.
Extension functions: permettono di aggiungere metodi a classi esistenti o di terze parti senza ricorrere all'ereditarietà.
Coroutines: pattern per la programmazione asincrona leggera e la gestione della concorrenza senza bloccare i thread primari.
Classi e metodi sono final di default; richiedono l'uso esplicito del modificatore open per l'ereditarietà.
Interoperabilità bidirezionale totale: è possibile chiamare codice Java da Kotlin e viceversa senza alcun overhead.
Q: Qual è la differenza tra l'operatore safe call ?. e l'operatore Elvis ?:?R: Il safe call ?. valuta la catena ed esegue l'operazione solo se l'oggetto non è null, altrimenti restituisce null in sicurezza. L'operatore Elvis ?: fornisce invece un valore di fallback esplicito se l'espressione alla sua sinistra risulta null.
Q: A cosa serve il modificatore inline in Kotlin?R: Serve a ottimizzare le funzioni di ordine superiore. Il compilatore copia il bytecode della funzione inline e delle lambda passate direttamente nel punto in cui viene chiamata, evitando l'allocazione di nuovi oggetti in memoria.
Q: Come si dichiara un pattern Singleton in Kotlin?R: Utilizzo direttamente la keyword object al posto di class. Il linguaggio gestisce automaticamente la singola istanza in modo thread-safe.
Abusare dell'operatore !! (not-null assertion) per forzare il bypass del compilatore, reintroducendo a runtime le eccezioni NullPointerException.
Dimenticare di gestire il lifecycle delle coroutines e non cancellare i Job attivi quando i componenti UI vengono distrutti, portando a gravi memory leak.
Esporre collezioni mutabili (MutableList) nelle interfacce pubbliche delle classi invece di isolarle tramite il tipo in sola lettura (List).
// Data class standard
data class User(val id: String, val email: String)
// Null safety: Safe call e operatore Elvis combinati
val usernameLength = user?.name?.length ?: 0
// Extension function per la classe String
fun String.isValidEmail(): Boolean {
return this.contains("@") && this.contains(".")
}
// Dichiarazione di un Singleton
object DatabaseClient {
fun connect() { /* ... */ }
}
// Esempio base di Coroutine con cambio di context
lifecycleScope.launch {
val data = withContext(Dispatchers.IO) {
// Esecuzione di task network o database sincroni (background)
fetchDataFromApi()
}
// Aggiornamento della UI in modo sicuro sul main thread
showData(data)
}