Java/Dal sorgente all'esecuzione

Indice del libro

Esempio pratico

modifica

Per scrivere ed eseguire un programma Java si seguono questi passi, che si tratti di un programma di esempio, di un'esercitazione, o di un applicativo per uso professionale. Ciò che cambia in questi passi è solo il testo del programma a meno che non venga utilizzato un ambiente di sviluppo come eclipse.

Passo 1: aprire l'editor di testo e scrivere questo:

public class PrimoProgramma {
    public static void main(String[] args) {
        System.out.println("Funziona!");
    }
}

Salva su un file chiamato PrimoProgramma.java.

Passo 2. Apri il terminale e portati nella cartella dove hai salvato il file. Quindi esegui

javac PrimoProgramma.java

Passo 3. Sempre sul terminale, esegui

java -cp . PrimoProgramma

Ora dovrebbe apparire una schermata come questa:

> cd progetti
> javac PrimoProgramma.java
> java -cp . PrimoProgramma
Funziona!
>

Se non è così, controllare di aver seguito le procedure spiegate in "Procurarsi il JDK".

Spiegazione

modifica

Ogni programma non è altro che una sequenza di istruzioni, scritta in un formato che il computer è in grado di comprendere ed eseguire.
Un programma Java si ottiene in due passi:

  1. Scrivendo i file che contengono il testo del programma;
  2. Eseguendo un programma apposito, chiamato compilatore, che legge i file e ne crea una versione eseguibile.

Il terzo passo avvia un programma chiamato macchina virtuale, che legge la versione eseguibile dei file, e la esegue istruzione per istruzione.
Un programma Java è diviso in moduli, ognuno dei quali prende il nome di classe. Nell'esempio sopra riportato, c'è una sola classe, che si chiama PrimoProgramma.

Spiegazione del passo 1

Il testo del programma è chiamato codice sorgente e contiene le istruzioni che il programma dovrà eseguire. La sequenza delle istruzioni comincia in un punto preciso del testo, che è individuato da questa riga (chiamata anche punto di ingresso o entry point):

    public static void main(String[] args) {

Le istruzioni terminano con la parentesi graffa corrispondente. In Java, tutte le parentesi - tonde, quadre, graffe - vanno sempre a coppie: ogni parentesi aperta vuole la sua parentesi chiusa.

In questo caso, il programma ha quattro parentesi graffe: due aperte e due chiuse. La prima parentesi graffa aperta appartiene alla classe e la seconda appartiene al main(), di conseguenza la prima parentesi graffa chiusa chiude il main() e la seconda chiude la classe.

Per scrivere il testo si usa un qualunque programma che permette di salvare i testi in formato *.txt. Quindi, su Windows, vanno bene il Blocco note e Wordpad; su Mac, TextEdit; e così via. I formati per documenti (per esempio, .odt, .doc, e altri), scritti con programmi come OpenOffice Writer oppure Microsoft Word, non vanno bene.
Ci sono programmi specializzati, che si chiamano IDE (Integrated Development Environment), che hanno funzioni speciali come la colorazione della sintassi, il completamento automatico dei nomi, ecc.

Spiegazione del passo 2

Il compilatore crea un duplicato del file sorgente, ma lo scrive in un formato diverso, che il computer è in grado di eseguire. Il compilatore usato nell'esempio di sopra è javac (Java compiler). Alcuni IDE hanno un tasto apposito che lancia in automatico il compilatore "dietro le quinte", il che è più comodo che invocarlo ogni volta da terminale.

Il testo prodotto dal compilatore si trova in alcuni file che hanno estensione .class. Questi sono leggibili solo dalla macchina virtuale.

Spiegazione del passo 3

La macchina virtuale prende in ingresso il nome della classe da avviare, cerca il file *.class corrispondente, ed esegue la sequenza di istruzioni identificata dal main(). Ogni classe può avere un solo main(), quindi non ci sono ambiguità.[1] Viceversa, se la classe non contiene il main(), la macchina virtuale si rifiuta di eseguire alcunché: ripetere i passi sopra usando questo codice sorgente, e vedere che succede.

public class PrimoProgramma {
}

In molti IDE c'è un pulsante che lancia la macchina virtuale in automatico. Il pulsante, in genere, è chiamato Run; alcuni offrono anche l'opzione Compile and Run.

Se javac termina senza scrivere nulla su console, la compilazione è avvenuta con successo. Altrimenti, possono apparire dei messaggi di errore (errors) e/o messaggi di avviso (warnings).

In genere, il programmatore neofita può ignorare i messaggi di avviso. Invece, se ci sono errori, il testo sorgente viola le regole del linguaggio, quindi è necessario leggere i messaggi di errore (che spesso sono in inglese), correggere i file interessati, facendo attenzione anche agli errori di battitura e all'accoppiamento delle parentesi graffe, e riprovare a compilare finché la procedura non riesce. Si noti che uno stesso errore può far sì che il compilatore interpreti male il testo che segue, fino alla fine del file, generando messaggi di errore superflui.

Se il prodotto del compilatore è eseguibile, perché devo lanciare la macchina virtuale? Non posso eseguirlo direttamente da terminale?
Dipende dal compilatore in uso. javac restituisce un formato che non è legato ad alcun sistema operativo, ed è appunto questo che rende Java portabile. L'altra faccia della medaglia è che il SO non riconosce direttamente il programma, quindi ci vuole un eseguibile a parte, che fa da intermediario tra il sistema operativo e il programma scritto in un formato di terze parti.
Esistono compilatori - come gcc - che restituiscono un formato binario eseguibile direttamente sul sistema operativo in uso, cioè avviabile senza la macchina virtuale, ma in quel caso si perde la portabilità: i file prodotti sono inutilizzabili su un sistema differente.

La macchina virtuale non può leggere direttamente il codice sorgente? Perché devo compilare?
È una scelta di chi scrive la macchina virtuale. È possibile scrivere una macchina virtuale che esegua direttamente il codice sorgente, ma finora gli sviluppatori della Sun (e della Oracle) non l'hanno ritenuto necessario.

Informazioni e consigli

modifica

Un programma può contenere vari tipi di errori.
Si parla di errore di sintassi se il programma contiene delle frasi che non hanno significato nel linguaggio di programmazione in uso; essi vengono rilevati dal compilatore, perché non possono essere compilati in quanto privi di senso.
Si parla di errore logico se il programma è corretto dal punto di vista della sintassi, ma contiene un comportamento anomalo, in luogo di quello desiderato dal programmatore. Ad esempio, a causa di un errore di battitura si può scrivere una istruzione invece di un'altra; entrambe corrette, ma dal significato diverso. Questi sono gli errori più pericolosi, perché il programma è compilabile e sembra funzionare correttamente, ma possono essere scoperti solo durante l'esecuzione.

La spaziatura è lasciata a discrezione del programmatore, tuttavia una buona indentazione rende il testo più chiaro e leggibile, e quindi facile da modificare anche dopo molto tempo. Non ci sono regole fisse, ma è buona norma

  • scrivere non più di una istruzione per ogni riga,
  • allineare tutte le istruzioni che appartengono ad uno stesso blocco di codice,
  • e far rientrare maggiormente quelle che appartengono a blocchi interni.

Inoltre, è molto importante aggiungere dei commenti che rendano il codice comprensibile anche ad altri: infatti, la stessa persona che l'ha scritto ne trarrà beneficio, quando rileggerà il codice a distanza di tempo. Anche in questo caso non esistono regole fisse, ma una buona norma di carattere generale è la seguente:

Se la ragione o lo scopo per cui è stata scritta una parte del testo non appare evidente dalla lettura dello stesso, aggiungere un breve commento esplicativo.

Infine, è bene dare sempre un nome breve, ma significativo, alle variabili, ai metodi, alle classi, e così via.

Un esempio:

class Calcolatrice {
    public static void main(String[] args) {
        // Definisco le variabili di ingresso e di uscita della calcolatrice
        int op1 = 1000;
        int op2 = 1100;
        char simbolo = '+';
        int risultato = 0;
        
        // Calcolo il risultato...
        switch(simbolo) {
        case '+':
            risultato = op1 + op2;
            break;
        case '-':
            risultato = op1 - op2;
            break;
        case '/':
            if (op2 == 0) {
                System.out.println("Impossibile calcolare: divisore uguale a zero! La divisione per zero non è definita.");
                return;
            } else {
                risultato = op1 / op2;
            }
            break;
        case '*':
            risultato = op1 * op2;
            break;
        }
        
        // ... e lo stampo a video
        System.out.println(risultato);
    }
}

Interazione con l'utente

modifica
  Per approfondire, vedi Input e output e AWT e Swing.

Il linguaggio Java permette la realizzazione di programmi a riga di comando (console) o programmi con interfaccia grafica (GUI). L'interazione con la riga di comando avviene attraverso i tre canali standard input, standard output, e standard error stream.

Che un programma funzioni a riga di comando o con GUI dipende da quale dei due meccanismi venga utilizzato. Il programmatore può utilizzare solo la console, o ignorare la console e interagire tramite interfaccia grafica, o ancora utilizzare entrambe. Al programmatore neofita si consiglia di utilizzare all'inizio la sola console, per poi approcciare alle interfacce grafiche in un momento successivo.

  1. Se nel codice sorgente ce ne sono di più, il compilatore si rifiuta: compilare il testo
    public class PrimoProgramma {
        public static void main(String[] args) {
            System.out.println("Funziona!");
        }
        public static void main(String[] args) {
            Syetem.out.println("Non funziona!");
        }
    }