Capitolo 11

Programmare in Kotlin con IntelliJ IDEA

Finora hai scritto ed eseguito il codice dentro questa pagina: comodissimo per imparare, perché vedi subito il risultato. Prima o poi però ti serve un vero ambiente di sviluppo, dove scrivere programmi completi, salvarli sul computer ed eseguirli con l'input che scrivi tu. Lo strumento giusto si chiama IntelliJ IDEA: è lo stesso che usano i programmatori di Kotlin sul lavoro, ed esiste in una versione gratuita (Community).

In questo capitolo impari

Ripasso lampo: tutto quello che ti serve nel progetto

In un progetto vero userai tutto il manuale: controlla con queste due domande.

Che cosa stampa questo programma se l'utente scrive 4, 6, 8?

fun main() {
    val voti = mutableListOf<Int>()
    for (i in 1..3) voti.add(readln().toInt())
    println(voti.sum())
    println(voti.max())
}
18 e 8Esatto: sum() somma tutti gli elementi, max() dà il più grande.
4 e 8No: sum() somma tutta la lista (4 + 6 + 8 = 18).
Un errore: max() su una lista vuotaLa lista non è vuota: il ciclo ha aggiunto tre elementi.

sum(), average(), max() e min() sono le versioni già pronte dello schema contatore/accumulatore: fanno un giro su tutta la lista e restituiscono il risultato.

Questo programma, aperto in un progetto vero, che cosa fa?

fun main() {
    val x = 3
    println(x * 2)
}
println("fuori")
Non compila: la println fuori da main non è valida in KotlinEsatto: fuori dalle funzioni si possono scrivere solo dichiarazioni (funzioni e classi), non istruzioni. Il compilatore si ferma prima ancora di eseguire. (Nel manuale questa riga gira lo stesso, ma compare un avviso che te lo ricorda.)
Stampa fuori e poi 6No: le istruzioni fuori da main non vengono eseguite. In un progetto vero non si arriva nemmeno a eseguire: il compilatore rifiuta il file.
Stampa solo 6 e ignora la riga fuoriQuesto era il comportamento del manuale nelle prime versioni, ed è quello che il motore fa ancora per non bloccarti: ma in Kotlin non è un programma valido, e il compilatore non lo accetta.
Stampa solo fuoriNo: il programma parte da main, che stampa 6; la riga fuori non è un programma valido.

In Kotlin ogni istruzione sta dentro una funzione, e il punto di partenza è fun main(). A livello superiore si dichiarano solo funzioni e classi. Se dimentichi le graffe di main, in IntelliJ vedrai un errore di compilazione: nel manuale, invece, il programma gira lo stesso ma ti avvisa con una nota gialla sopra il pannello delle variabili.

11.1 Perché passare a un IDE

Questa pagina è un laboratorio didattico: esegue i costrutti spiegati nel capitolo, ma non è un IDE. Un IDE (Integrated Development Environment, ambiente di sviluppo integrato) è un programma che riunisce tutto quello che serve: editor con colori, controllo degli errori mentre scrivi, suggerimenti automatici, esecuzione del programma e console per l'input/output.

Qui nel manualeIn IntelliJ IDEA
il codice vive nella pagina, non si salvail codice è un file sul tuo computer: lo salvi e lo riapri quando vuoi
solo i costrutti studiati finoratutto il linguaggio Kotlin e tutte le librerie
l'input si scrive nella console, con il cursore in coda all'outputl'input si scrive nella finestra Run, cliccandoci dentro quando il programma è in attesa
Ctrl+D o il pulsante ⏹ fine dei dati dicono che i dati sono finiti (readlnOrNull() restituisce null, mentre readln() si ferma con un errore)la stessa cosa succede quando lo standard input viene chiuso (fine dell'input)
errori spiegati e tradotti per chi imparaerrori e avvisi mentre scrivi, riga per riga
ideale per capire un concetto in 2 minutiideale per scrivere davvero i tuoi programmi
Perché non i siti di prova online

Esistono siti "playground" che eseguono Kotlin nel browser. Sono comodi per una prova veloce senza input, ma non permettono di scrivere i dati durante l'esecuzione: appena il programma chiama readln() si blocca in attesa di un dato che non puoi digitare. Per questo, quando passi a programmi con input, usa IntelliJ IDEA.

11.2 Che cosa serve: il JDK e IntelliJ IDEA

Un programma Kotlin non viene eseguito "direttamente" dal computer: prima viene compilato e poi eseguito dalla macchina virtuale Java. Per questo servono due pezzi:

I passi dell'installazione
  1. Vai sul sito di JetBrains e scarica IntelliJ IDEA Community Edition per il tuo sistema operativo.
  2. Apri il file scaricato e installa, accettando le impostazioni proposte (su Windows ricorda la spunta per creare l'icona sul desktop).
  3. Al primo avvio accetta la licenza e scegli un tema chiaro o scuro: sono solo preferenze personali.
  4. Se compare la richiesta di installare un JDK, accetta: IntelliJ lo scarica in automatico.

11.3 Creare il primo progetto

Un progetto è la cartella che contiene tutti i file di un programma. Si crea una volta sola:

  1. nella schermata iniziale premi New Project;
  2. a sinistra scegli Kotlin (non "Kotlin Multiplatform", non "Android");
  3. in Name scrivi un nome senza spazi, per esempio PrimoKotlin;
  4. controlla la Location, cioè la cartella in cui verrà salvato il progetto;
  5. se il campo JDK è vuoto, scegli Download JDK... e lascia le impostazioni proposte;
  6. premi Create e aspetta qualche secondo mentre IntelliJ prepara il progetto.

Alla fine hai davanti tre zone: a sinistra il Project (l'elenco dei file), al centro l'editor (dove scrivi il codice), in basso la finestra Run (dove compaiono output ed errori).

Dove sta il mio codice?

IntelliJ crea da solo il file src/main/kotlin/Main.kt con dentro un programma di esempio. src è la cartella dei sorgenti, main la parte principale, kotlin indica il linguaggio, Main.kt è il file (.kt è l'estensione di Kotlin). Per aggiungere un file: clic destro su kotlinNewKotlin Class/FileFile, poi scrivi il nome.

11.4 Il primo programma: fun main

In Kotlin un programma completo comincia da una funzione speciale, fun main(): le istruzioni scritte fra le sue parentesi graffe sono quelle che vengono eseguite. Nel manuale potevi scrivere le istruzioni "sciolte"; in un progetto vero vanno dentro main.

  1. In un progetto vero Kotlin esegue solo la funzione main: qui dentro ci sono le istruzioni che vedi.
  2. println("Ciao") stampa la prima riga; println(2 + 3) stampa 5, perché le parentesi contengono un'espressione che Kotlin calcola prima di stampare.
  3. Se ci fosse una println fuori da main, in IntelliJ non verrebbe eseguita.

Copia questo codice con 📋 Copia, cancellalo dentro Main.kt e incollalo al suo posto: è esattamente la forma che vedrai in IntelliJ.

Le graffe si contano

Ogni { deve avere la sua } e le istruzioni si scrivono dentro le graffe di main. IntelliJ rientra automaticamente le righe e chiude le graffe al posto tuo: fidati del rientro, se una riga non è allineata con le altre c'è qualcosa che non va.

11.5 Eseguire il programma

Per eseguire un programma ci sono due strade, e danno lo stesso risultato:

ComeCosa fare
Triangolino verde è accanto a fun main() e in alto a destra: cliccalo e scegli Run
TastieraShift+F10 su Windows e Linux, Ctrl+R su Mac

La prima volta IntelliJ compila il programma (ci mette qualche secondo in più), poi apre in basso la finestra Run con l'output:

Ciao dal mio primo progetto Kotlin!
Questo programma lo esegui con il triangolino verde.
Se qualcosa non parte

11.6 Leggere i dati con readln in IntelliJ

Questo è il punto che fa perdere più tempo ai principianti. In Kotlin i dati si leggono con readln(), che aspetta una riga scritta da chi usa il programma. In IntelliJ non esiste una casella da riempire prima: i dati si scrivono nella finestra Run mentre il programma è in attesa. Anche la console di questo manuale funziona così: il programma si ferma sulla readln(), il cursore si mette in coda all'output, tu scrivi il valore e premi Invio. La differenza è che in IntelliJ scrivi nel riquadro Run (dopo averci cliccato dentro), qui nel riquadro nero sotto il codice.

Hai premuto Run e il programma ha stampato la domanda, poi sembra essersi fermato. Che cosa fai?

Premi di nuovo RunCosì avvii un secondo programma mentre il primo aspetta ancora: è uno degli errori più comuni.
Clicchi dentro la finestra Run e scrivi il valore, poi premi InvioEsatto: il programma è in attesa della tua readln(); finché non premi Invio non può andare avanti.
Chiudi e riapri il progettoNon serve: non c'è nessun errore, il programma sta solo aspettando te.

Lo stesso vale qui nel manuale: quando lo stato dice ⏸ in attesa di dati…, il cursore è in coda all'output e aspetta una riga scritta da te.

Come si fa, passo per passo, in IntelliJ
  1. premi Run: nella finestra in basso leggi Come ti chiami?;
  2. il programma si è fermato e aspetta: clicca dentro la finestra Run (così il cursore lampeggiante va su quella finestra);
  3. scrivi Giulia e premi Invio;
  4. compare Quanti anni hai?: scrivi 16 e premi Invio;
  5. il programma stampa Ciao Giulia, hai 16 anni. e termina.

Una riga di testo per ogni readln(), nello stesso ordine in cui le chiede il programma. Se premi Invio senza scrivere nulla, il programma riceve una stringa vuota: è un dato valido, ma poi toInt() fallirà.

Tre trappole dell'input in IntelliJ

Quando ci sono più dati da leggere, si usa un ciclo: readln() verrà chiamato una volta per ogni giro e ogni volta leggerà la riga successiva.

  1. print (senza ln) lascia il cursore sulla stessa riga della domanda: per questo il 2008 e il 2026 che scrivi appaiono attaccati alle rispettive domande.
  2. Nella finestra Run di IntelliJ i valori scritti da te restano nell'output, come qui: fanno parte della conversazione con il programma.
  3. L'anno attuale arriva dall'input, non da un numero scritto nel codice: un programma vero leggerebbe l'orologio del computer, qui per semplicità lo chiediamo a chi lo usa. Il calcolo dà 18.

Un progetto vero può avere anche più file: la data class in un file e il programma in un altro, oppure tutto insieme, come qui. In Kotlin le classi e le funzioni definite a livello superiore sono visibili da tutto il progetto.

In IntelliJ una riga è sottolineata in rosso e il pulsante Run è grigio. Che cosa significa?

C'è un errore di compilazione: il programma non può partireEsatto: la sottolineatura rossa è un errore vero, e va corretto prima di eseguire. Il giallo, invece, è solo un avviso.
È solo un avviso: posso eseguire lo stessoGli avvisi sono in giallo. Il rosso impedisce la compilazione.
Il JDK non è installatoSe mancasse il JDK te lo direbbe IntelliJ con un messaggio dedicato; una riga rossa è un errore nel codice.

Per capire che cosa non va, passa il mouse sulla parola sottolineata: IntelliJ spiega l'errore, e spesso propone la correzione.

11.7 Errori frequenti in IntelliJ

IntelliJ sottolinea in rosso gli errori veri (il programma non parte) e in giallo gli avvisi (parte, ma c'è qualcosa da sistemare). Passa il mouse sulla parola sottolineata per leggere la spiegazione.

MessaggioChe cosa significaCome si risolve
Unresolved reference: nome Kotlin non conosce nome: o l'hai scritto male, o non l'hai ancora dichiarato controlla maiuscole/minuscole e dichiara la variabile prima di usarla
Expecting '}' / Expecting ')' manca una graffa o una parentesi di chiusura vai sulla riga indicata e conta le graffe; in fondo al file controlla l'ultima
Kotlin is not configured il progetto non è stato creato come progetto Kotlin ricrea il progetto scegliendo Kotlin nella schermata New Project
Val cannot be reassigned stai cambiando una variabile dichiarata con val se il valore deve cambiare, dichiara la variabile con var
Please specify the JDK manca il motore che esegue i programmi FileProject StructureSDKDownload JDK...
Exception in thread "main" java.lang.NumberFormatException stai convertendo con toInt() un testo che non è un numero (per esempio un dato vuoto) scrivi il dato numerico nel giro giusto, oppure usa toIntOrNull()

11.8 Scorciatoie da tastiera che fanno risparmiare tempo

Windows / LinuxMacCosa fa
Shift+F10Ctrl+Resegue il programma un'altra volta
Ctrl+SpazioCtrl+Spaziosuggerisce come completare quello che stai scrivendo (su Mac può essere occupato dal cambio sorgente di input: si imposta nelle preferenze)
Alt+InvioOption+Inviopropone la correzione rapida dell'errore sotto il cursore
Ctrl+/Cmd+/trasforma la riga in commento e viceversa
Ctrl+DCmd+Dduplica la riga (comoda per righe simili)
Ctrl+Alt+LCmd+Option+Lrimette ordine e rientro in tutto il file
Ctrl+ZCmd+Zannulla l'ultima modifica: sbagliare non è un problema
Ctrl+FCmd+Fcerca una parola nel file

11.9 Riepilogo

AzioneCome
Creare il progettoNew ProjectKotlin → nome → Create
Dove scrivo il codicesrc/main/kotlin, per esempio Main.kt
Dove inizia il programmafun main() { ... }
Eseguiretriangolino verde oppure Shift+F10 (Ctrl+R su Mac)
Vedere l'outputfinestra Run, in basso
Dare i dati in inputdopo il Run, clic dentro la finestra Run, scrivi il dato e premi Invio
Leggere un datoval x = readln() (testo), readln().toInt() (intero), readln().toDouble() (decimale)
Aggiungere un fileclic destro sulla cartella kotlinNewKotlin Class/FileFile
Fermare un programma in attesaquadratino rosso (Stop)

11.10 Esercizi guidati

Completa il programma come lo scriveresti in Main.kt: dentro fun main() leggi il nome, l'anno di nascita e l'anno in cui siamo, calcola l'età quest'anno e stampa un saluto con nome, anno ed età. L'anno in cui siamo si legge dall'input: un programma vero leggerebbe l'orologio del computer, qui per semplicità lo chiediamo a chi lo usa. Con i dati Giulia, 2008, 2026 il programma deve stampare Ciao Giulia!, Sei nato/a nel 2008, quindi quest'anno compi 18 anni. e infine A presto, Giulia!.

Per leggere un numero scrivi val anno = readln().toInt(). L'anno in cui siamo si legge dall'input, non si scrive nel codice: l'età è annoAttuale - anno. Per unire testo e variabili usa il template di stringa: "Ciao $nome!".

  1. Tutto il codice sta dentro le graffe di fun main(): è la forma che IntelliJ si aspetta per poter avviare il programma.
  2. readln() restituisce una String; per fare un calcolo serve toInt(), che trasforma il testo in numero intero.
  3. L'anno in cui siamo si legge dall'input e finisce nella costante annoAttuale: l'età è annoAttuale - anno. Un programma vero leggerebbe l'orologio del computer; qui per semplicità lo chiediamo a chi lo usa, e così il calcolo resta giusto in qualsiasi anno.
  4. Nel template di stringa "Ciao $nome!" il simbolo $ inserisce il valore della variabile dentro il testo: è più leggibile delle concatenazioni con +.
  5. In IntelliJ, per provarlo: incolla il codice in Main.kt, premi Shift+F10, clicca nella finestra Run e scrivi Giulia, Invio, 2008, Invio, 2026, Invio.

Programma completo: chiedi quanti numeri verranno inseriti, leggili tutti in un ciclo e stampa la somma, la media (due decimali) e il numero più grande. Ricorda di mettere tutto dentro fun main().

Prima del ciclo prepara var somma = 0 e var massimo = 0. Dentro il ciclo leggi con val n = readln().toInt(), aggiungi alla somma con somma += n e aggiorna il massimo con if (n > massimo) massimo = n.

  1. Le variabili somma e massimo si preparano prima del ciclo: se le dichiarassi dentro, verrebbero azzerate a ogni giro.
  2. for (i in 1..quanti) ripete il blocco esattamente quanti volte; a ogni giro readln() legge la riga successiva scritta nella finestra Run.
  3. somma += n è la forma breve di somma = somma + n.
  4. Il massimo si trova confrontando: if (n > massimo) massimo = n tiene solo il valore più alto visto finora.
  5. somma.toDouble() / quanti fa la divisione con i decimali: senza toDouble() Kotlin dividerebbe fra interi e perderebbe la parte decimale.

Crea la data class Studente(val nome: String, val voto: Int) a livello superiore (fuori da main, come si fa nei progetti veri) e dentro fun main() leggi tre studenti (nome e voto), mettili in una lista e stampa: l'elenco, quanti sono insufficienti (voto minore di 6), il migliore e la media dei voti con due decimali.

Insufficienti: registro.count { it.voto < 6 }. Migliore: registro.maxByOrNull { it.voto } (controlla che non sia null). Media: registro.map { it.voto }.average().

  1. La data class sta fuori da main: descrive un tipo di dato e può essere usata da tutto il file (e da altri file del progetto).
  2. La lista è mutableListOf perché cresce dentro il ciclo con add: non sappiamo i dati in anticipo.
  3. Ogni giro legge due righe: il nome e il voto. In IntelliJ le scrivi una per volta nella finestra Run, premendo Invio.
  4. count { it.voto < 6 } conta gli studenti che soddisfano la condizione, senza scrivere un ciclo a mano.
  5. maxByOrNull restituisce lo studente col voto più alto, ma il tipo può essere null: il controllo if (migliore != null) è la prassi per usarlo in sicurezza.
  6. average() restituisce un numero decimale: "%.2f".format(media) lo stampa con due cifre dopo la virgola.

Questo è l'esercizio di chiusura del manuale: scrivi da zero un programma completo, come lo scriveresti in Main.kt. Prima della fun main() dichiara una data class Prodotto(val nome: String, val prezzo: Double, val quantita: Int) con un metodo totale() che restituisce prezzo * quantita.

Dentro main, leggi tre prodotti (per ognuno: nome, prezzo e quantità, in questo ordine — una riga per dato), mettili in una lista e stampa: l'elenco con il totale di ogni riga (due decimali), il nome dell'articolo più costoso (quello con il totale() maggiore) e l'elenco degli articoli da riordinare, cioè quelli con quantità 0. Se non c'è nessun articolo da riordinare, stampa Nessun articolo da riordinare.

Caso limite: se il prezzo di un prodotto non si legge (per esempio una riga vuota), consideralo 0.0 e vai avanti senza fermare il programma. Con i dati di prova l'output deve contenere Quaderno 2.50 x 4 = 10.00 euro, Articolo piu costoso: Zaino e Da riordinare: Penna.

La struttura: prima la data class fuori da main, poi dentro main un ciclo for (i in 1..3) che a ogni giro legge le tre righe e riempie una mutableListOf<Prodotto>(). Per l'articolo più costoso usa maxByOrNull { it.totale() } con il controllo != null; per i riordini filter { it.quantita == 0 } e isEmpty().

  1. La data class sta fuori da main e il suo metodo totale() calcola una proprietà derivata: scritto una volta, si usa nell'elenco, nella ricerca del massimo e in quella dei riordini.
  2. Le tre letture a ogni giro rispettano l'ordine dei dati (nome, prezzo, quantità) e i valori di riserva ?: 0.0 e ?: 0 coprono i numeri mancanti o sporchi: il programma non si ferma mai per un prezzo o una quantità che non si capiscono.
  3. maxByOrNull { it.totale() } cerca l'oggetto con il totale maggiore e può restituire null se la lista è vuota: il controllo if (piuCaro != null) è la prassi vista nel capitolo 10.
  4. filter { it.quantita == 0 } costruisce l'elenco dei riordini e isEmpty() distingue i due casi: l'attenzione alle liste vuote è lo stesso schema dell'esercizio da zero del capitolo 6.
  5. Il programma è identico a quello che scriveresti in IntelliJ: incollalo in Main.kt, premi Shift+F10 e dai i dati nella finestra Run, una riga per volta.

Questo è il programma di un progetto IntelliJ: deve chiedere il nome e salutare, ma non parte e non stampa niente. Correggilo: alla fine deve scrivere Ciao Giulia!.

Il programma non ha errori di scrittura: è il nome della funzione a essere sbagliato. Kotlin cerca un punto di partenza con un nome preciso, tutto minuscolo, e se non lo trova non esegue nulla.

  1. Il programma parte da una funzione chiamata main, tutta minuscola: è l'unico nome che Kotlin accetta come punto di partenza.
  2. Kotlin distingue maiuscole e minuscole, quindi Main e main sono due nomi diversi: fun Main() è una funzione come le altre, e nessuno la chiama.
  3. Il sintomo è proprio questo: il pulsante Run non trova niente da eseguire e la console resta vuota, senza messaggi di errore. Un programma che non parte non sempre ha un errore di sintassi: a volte semplicemente non ha un punto di partenza.
  4. Cambiando la sola lettera il programma funziona: chiede il nome, aspetta il dato e saluta.
  • so spiegare che cosa sono un IDE e il JDK
  • so installare IntelliJ IDEA Community e creare un nuovo progetto Kotlin
  • so scrivere fun main() { ... } e farlo partire con Run
  • so scrivere i dati nella finestra Run e so che non si preparano prima
  • so distinguere un errore (rosso) da un avviso (giallo)
  • so copiare un programma del manuale nel progetto e farlo funzionare
  • so leggere un messaggio di errore e correggere il programma da solo