Kotlin è un linguaggio di programmazione tipizzato staticamente di JetBrains, che funziona su JVM ed è ufficialmente supportato da Google per lo sviluppo Android dal 2017. Kotlin è completamente compatibile con Java, ha una sintassi concisa e null safety integrata. Kotlin Documentation — guida completa al linguaggio e alla libreria standard.
Punti Chiave
Kotlin è un linguaggio di programmazione tipizzato staticamente creato da JetBrains (sviluppatore di IntelliJ IDEA) e rilasciato nel 2016 sotto licenza Apache 2.0. Kotlin compila in bytecode JVM, JavaScript e codice nativo (tramite Kotlin/Native). I suoi principali ambiti di applicazione sono lo sviluppo Android, le applicazioni lato server e i progetti multipiattaforma.
Google ha annunciato Kotlin come linguaggio ufficiale per lo sviluppo Android al Google I/O 2017. Secondo Google (Android Developer Blog, 2026), oltre l'85% dei nuovi progetti su Google Play utilizza Kotlin. Il linguaggio è anche attivamente utilizzato nello sviluppo server (Spring Boot, Ktor) e nei progetti multipiattaforma (Kotlin Multiplatform Mobile).
Kotlin è completamente compatibile con Java — puoi chiamare codice Java da Kotlin e viceversa nello stesso progetto. Gli strumenti di build (Gradle, Maven) supportano entrambi i linguaggi, consentendo una migrazione graduale da Java a Kotlin senza tempi di inattività nello sviluppo.
Le ragioni principali: concisione — Kotlin richiede in media il 40% in meno di righe di codice rispetto a Java per lo stesso compito. Null safety — il compilatore proibisce l'uso di tipi nullable senza controllo. Capacità funzionali — funzioni di ordine superiore, lambda, funzioni di estensione e coroutine rendono il codice più espressivo e sicuro.
La sintassi di base di Kotlin combina concisione e chiarezza. Le variabili vengono dichiarate con val (immutabile) e var (mutabile). Il compilatore usa l'inferenza dei tipi, ma la dichiarazione esplicita del tipo è supportata. Le funzioni vengono dichiarate con la parola chiave fun.
package com.example.intro
// Costanti e variabili
val appName: String = "KotlinApp" // immutabile
var version = 1.0 // mutabile, tipo inferito
// Funzione con expression body
fun sum(a: Int, b: Int) = a + b
// String templates
fun greet(name: String) = "Ciao, $name! Versione ${appName}_$version"
// Default and named arguments
fun createUser(
name: String,
age: Int = 18,
email: String? = null
)L'espressione when sostituisce switch in Java ed è più flessibile: supporta controlli di tipo, intervalli, condizioni e rami senza break. Il compilatore verifica la copertura esaustiva per classi enum e sealed. Gli smart cast convertono automaticamente i tipi dopo un controllo is, eliminando cast espliciti.
fun analyzeValue(value: Any) = when (value) {
is String -> "Stringa di lunghezza ${value.length}" // smart cast
is Int -> "Numero intero: $value"
in 1..10 -> "Numero nell'intervallo 1-10"
else -> "Tipo sconosciuto"
}Null safety è una caratteristica fondamentale di Kotlin che elimina NullPointerException in fase di compilazione. In Kotlin, i tipi non possono essere null per impostazione predefinita. Per consentire null, aggiungi ? al tipo: String?. Il compilatore richiede un controllo esplicito di ogni valore nullable.
// Tipi nullable e non-null
val nonNull: String = "Sempre non null"
val nullable: String? = null // consentito
// Safe call — esegue solo se non null
val length: Int? = nullable?.length
// Operatore Elvis — valore predefinito
val text: String = nullable ?: "Default text"
// Let — esegui blocco con valore non-null
nullable?.let { value ->
println("Valore: $value")
}L'operatore safe call (?.) restituisce null se l'oggetto prima dell'operatore è null e chiama il metodo/proprietà altrimenti. L'operatore Elvis (?:) fornisce un valore predefinito se la parte sinistra è null. L'asserzione not-null (!!) lancia NullPointerException se il valore è null — usala solo quando sei sicuro al 100% che il valore esista.
Tipi platform — tipi Java dal codice Java chiamato che Kotlin non può marcare come nullable o non-null. Il tipo viene visualizzato come String! (con punto esclamativo). Lo sviluppatore è responsabile della null safety quando lavora con codice Java.
Le data class in Kotlin generano automaticamente equals(), hashCode(), toString(), copy() e componentN(). Questo elimina il boilerplate dei modelli Java (POJO) e rende il codice più pulito. Dichiarare una data class richiede una riga invece di 20-30 in Java.
data class User(
val id: Long,
val name: String,
val email: String,
val age: Int? = null
)
// Utilizzo
val user = User(1, "Anna", "anna@example.com")
val updatedUser = user.copy(age = 25)
// Destrutturazione
val (id, name) = user
println("Utente #$id: $name")La destrutturazione permette di scomporre una data class in variabili in una singola riga. Questo è comodo quando si lavora con coppie, triple e altri valori compositi. La destrutturazione è supportata per data class, collezioni standard (List, Map) e qualsiasi classe con operator fun componentN().
Le funzioni di estensione sono un meccanismo di Kotlin per aggiungere nuovi metodi a classi esistenti senza ereditarietà. Le estensioni vengono compilate in metodi statici con un parametro receiver, quindi l'ereditarietà non è richiesta e il dispatch virtuale non è supportato.
// Funzione di estensione per String
fun String.isEmail(): Boolean {
return this.contains("@") && this.contains(".")
}
// Proprietà di estensione
val String.isPhoneNumber: Boolean
get() = this.matches(Regex("^\\+?[\\d-]{10,15}$"))
// Estensione generica per collezioni
fun List<Int>.sumOfEvens(): Int {
return this.filter { it % 2 == 0 }.sum()
}
// Utilizzo
println("test@mail.com".isEmail()) // trueLe estensioni sono ampiamente utilizzate nell'Android SDK e nelle librerie. Ad esempio, le Activity extensions in Android KTX sono funzioni di estensione per Activity, Fragment, View e altre classi. Le estensioni possono essere dichiarate come funzioni di livello superiore in un file o come estensioni membro di una classe.
Le coroutine sono un meccanismo di programmazione asincrona in Kotlin che permette di scrivere codice non bloccante in stile sequenziale. Una coroutine sospende l'esecuzione su una funzione suspend senza bloccare il thread e riprende dopo il completamento dell'operazione. È un'alternativa alle catene di callback RxJava e AsyncTask.
import kotlinx.coroutines.*
// Funzione suspend — può sospendersi
suspend fun fetchUserData(userId: Int): User {
// delay — funzione suspend, non blocca il thread
delay(500)
return User(userId, "User $userId", "user@example.com")
}
// Avvia in coroutine
fun loadData() {
CoroutineScope(Dispatchers.Main).launch {
val user = fetchUserData(1) // pausa qui
updateUI(user) // continua sul thread Main
}
}I Dispatchers determinano il pool di thread per una coroutine: Dispatchers.Main (thread UI), Dispatchers.IO (operazioni di rete/disco), Dispatchers.Default (attività intensive per CPU). La concorrenza strutturata garantisce che una coroutine non rimanga attiva dopo il completamento dello scope — questo previene perdite di memoria.
// Esecuzione parallela tramite async/await
suspend fun loadDashboard(): Dashboard = coroutineScope {
val user = async { fetchUserData(1) }
val orders = async { fetchOrders(1) }
val stats = async { fetchStats() }
Dashboard(user.await(), orders.await(), stats.await())
}La scelta tra Kotlin e Java per un nuovo progetto Android è una decisione architetturale fondamentale. Kotlin offre una sintassi più moderna e meccanismi di sicurezza integrati, mentre Java ha un pool più ampio di sviluppatori e librerie mature.
| Caratteristica | Kotlin | Java |
|---|---|---|
| Null safety | Integrata (nullable/non-null) | Non integrata (annotazioni @Nullable) |
| Volume di codice | −40% rispetto a Java | Boilerplate (getters/setters) |
| Data class | data class (una riga) | POJO con Lombok o manuale |
| Asincronia | Coroutine (suspend/await) | CompletableFuture, RxJava |
| Funzioni di estensione | Integrate | Solo tramite classi utility |
| Smart cast | Dopo controllo is | Cast esplicito (Type) obj |
| Compatibilità all'indietro | 100% con Java | — |
Prestazioni di Kotlin e Java sono comparabili — entrambi compilano in bytecode JVM. Kotlin a volte aggiunge un micro-overhead per coroutine e inlining, ma è trascurabile per le applicazioni mobili. Google e JetBrains investono attivamente in Kotlin: Kotlin Multiplatform, Kotlin/Wasm e miglioramenti delle prestazioni del compilatore K2.
Domande Frequenti
Kotlin è 40% più corto di Java — meno boilerplate. Kotlin aggiunge null safety, data class, funzioni di estensione, coroutine, smart cast, espressioni when. Compatibilità totale con Java: entrambi i linguaggi funzionano su JVM e possono essere usati nello stesso progetto senza conflitti.
I tipi sono non-null per impostazione predefinita. Per nullable usa ?: String?. Il compilatore proibisce l'accesso diretto a valori nullable. Safe call (?.) restituisce null su ricevitore null. Operatore Elvis (?:) imposta un valore predefinito. !! — estrazione forzata con possibile eccezione.
Le coroutine sono thread leggeri che permettono di scrivere codice asincrono in modo sequenziale. Le funzioni suspend si mettono in pausa senza bloccare il thread. launch e async avviano coroutine in CoroutineScope. Dispatchers.IO per richieste di rete, Dispatchers.Main per aggiornamenti UI.
data class genera automaticamente equals(), hashCode(), toString(), copy() e componentN(). Esempio: data class User(val name: String, val age: Int). Destrutturazione tramite val (name, age) = user. Simile a record in Java 14+, ma con il metodo aggiuntivo copy().
Le funzioni di estensione aggiungono metodi a classi esistenti: fun String.isEmail(): Boolean. Il compilatore le sostituisce con chiamate statiche con un parametro receiver. Non è richiesta ereditarietà. Le estensioni sono ampiamente utilizzate in Android KTX: view.showToast(), activity.viewModels().
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche