Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Il programma consiste di una sola classe, di nome HelloWorld, che contiene un solo metodo chiamato
main. I membri della classe sono scritti tra le parentesi graffe { e } che delimitano il corpo della classe.
HelloWorld ha un unico metodo e non ha variabili. L’unico parametro del metodo main è un
vettore di oggetti di tipo String: in questo vettore si troveranno gli argomenti forniti al programma al
momento del suo avvio. Il metodo main è un metodo speciale: si tratta infatti del metodo che viene
eseguito quando si lancia una classe come applicazione a sé stante.
Nell’esempio, il metodo main contiene una sola istruzione che richiama il metodo println
dell’oggetto out della classe System. Un metodo viene richiamato utilizzando un riferimento ad un
1
oggetto e individuandolo, con l’operatore punto (.) seguito dal nome del metodo. Il metodo println
dell’oggetto out stampa una stringa seguita da un a capo.
Per poter eseguire il programma HelloWorld, occorre prima invocare il compilatore Java per
produrre il byte code eseguibile e quindi invocare l’interprete Java.
Applet
Un applet è una applicazione Java che viene invocata dall’interno di un browser o di un’altra
applicazione. Tutto quanto serve per il funzionamento di un applet è racchiuso nella classe Applet,
perciò per creare un applet è sufficiente definire una classe che eredita dalla classe Applet.
Inoltre un applet non viene lanciata direttamente perciò non ha bisogno di un metodo main(). Essa
viene lanciata all’interno di un proprio thread ed ha diverse fasi di vita in cui può passare da essere
attiva a inattiva fino a quando viene fatta terminare. Quando un applet viene lanciata all’interno di un
browser, questo le affida un’area della finestra nella quale può disegnare. Ecco una esempio di una
semplice applet che scrive una frase sullo schermo:
import java.applet.Applet;
import java.awt.Graphics;
Classi
In Java l’unità fondamentale dei programmi è la classe. Le classi contengono i metodi, formati da
sequenze di codice eseguibile, sulle quali si basa la computazione. Le classi inoltre determinano la
struttura degli oggetti.
Uno dei cardini della programmazione ad oggetti è la separazione tra “che cosa” deve essere fatto
e “come” viene fatto. Il “che cosa” viene descritto dall’interfaccia pubblica di una classe, che è
costituita dai metodi (e dagli attributi) che una classe rende disponibili all’esterno. Il “come” è
costituito dal codice che implementa i metodi. Per poter usare un oggetto è sufficiente conoscere quali
metodi esso rende disponibili, senza dover conoscere come sono implementati. Questo consente di
poter cambiare l’implementazione di una classe senza che ciò si ripercuota sui programmi che la
usano.
Metodi
Le funzionalità di una classe sono fornite dai suoi metodi, che ne realizzano l’interfaccia. Un metodo
è una procedura con parametri che può venire invocata sugli oggetti della classe. Esso viene definito
all’interno della classe come nell’esempio precedente:
public void paint(Graphics g) {
g.drawString("Hello world!", 50, 25);
}
2
In questo caso paint è il nome del metodo, e g è il parametro di tipo Graphics. Nel corpo del metodo si
vede l’invocazione al metodo drawString dell’oggetto g, che fa uso della notazione col punto (dot
notation).
In Java è possibile che in una classe siano definiti più metodi con lo stesso nome, ma con diversa
lista di parametri. Si tratta del cosiddetto overloading, che consente di designare con un nome unico
un’operazione che può essere svolta in differenti modalità. Ad esempio, nella classe Graphics
potrebbe esistere anche un altra definizione per drawString:
void drawString(String s, Point p)
Eccezioni
Per evitare che un programma produca effetti indesiderati, sarebbe buona norma controllare che ogni
operazione si sia conclusa senza errori, ad esempio che la lettura di un file non abbia superato il suo
limite o che un’operazione aritmetica abbia prodotto un overflow. Tuttavia l’aggiunta di questi
controlli rende il programma molto più complesso e ne rende incomprensibile il flusso logico. Spesso
chi programma in un linguaggio di programmazione tradizionale preferisce evitare di inserire questi
controlli nella presunzione che situazioni anormali non si verifichino. Questo dà origine a programmi
che a volte si piantano o producono comportamenti imprevisti.
Per evitare queste situazioni, che possono essere particolarmente fastidiose per chi sta eseguendo
un programma altrui scaricato dalla rete, Java dispone di un meccanismo di trattamento delle
eccezioni controllate.
Un metodo che rileva una situazione di errore, che non gli consente di portare a termine
normalmente l’operazione, lancia (throw) un’eccezione. L’eccezione è un oggetto di solito derivato
dalla classe Exception. Il metodo deve riportare in una clausola throws nella sua dichiarazione i tipi
di eccezione che può provocare. Un programma che invoca un metodo che produce un’eccezione deve
occuparsi di gestire tale eccezione o quanto meno dichiarare a sua volta di provocare tale eccezione. Il
compilatore Java assicura che ogni possibile eccezione generata sia trattata in qualche parte del
programma.
Il paradigma di uso delle eccezioni è la sequenza try-catch-finally. Si tenta (try) un’operazione,
se questa produce un’eccezione, la si intercetta (catch) ed infine (finally) si rimette il programma in
condizioni di proseguire.
Vediamo un esempio di uso delle eccezioni nel metodo mediaDi che calcola la media di due valori
di un array. Se un indice cade al di fuori dei limiti dell’array, viene provocata l’eccezione
MediaIllegale.
Questo nuovo tipo di eccezione viene dichiarato con la definizione:
class MediaIllegale extends Exception {}
Le operazioni di accesso ad elementi di matrici in Java sono soggette al controllo sui limiti degli
indici. Qualora tale controllo non venga superato, viene generata un’eccezione di tipo
IndexOutOfBoundsException.
3
Package
Quando si scrivono programmi complessi o si mettono insieme programmi scritti da altri, aumenta il
rischio di conflitti tra i nomi delle classi o dei metodi. Il meccanismo dei package di Java consente di
risolvere questo problema: una classe viene inserita in un package ed i nomi che usa hanno validità
solo all’interno del package. I package hanno un nome e possono importati. I package contengono tipi
e sottopackage. I nomi dei package sono pertanto gerarchici, con componenti separati da un punto.
Tramite la clausola import si possono rendere accessibili da un metodo tutto o singoli elementi di
un package. In alternativa si possono indicare direttamente nomi all’interno di un package usando la
forma qualificata del nome che consiste nel nome del package seguito dal nome del componente
separato da un punto.
Ad esempio possiamo far uso della classe Date, che fa parte del package java.util, in questo modo:
java.util.Date = new Date();
Oppure iniziando il programma con:
import java.util.Date;
e scrivendo in seguito