professionale

Java: Arte e tecnica
Sintassi e struttura del linguaggio

Dario de Judicibus

Descritta la grammatica base di un linguaggio, iniziamo ad approfondire l’analisi di Java con l’obiettivo di descriverne le caratteristiche, sia al programmatore esperto sia a quanti si avvicinano per la prima volta ad un linguaggio di programmazione. Un’attenzione particolare sarα rivolta a quei lettori che giα conoscono il C++ e che desiderano passare a Java.

 

Dopo i due servizi di premessa pubblicati a ottobre e novembre, iniziamo a fare la conoscenza di Java con una serie di articoli strutturati in modo tale che ciascuno sia funzionale innanzitutto a quanti non sanno programmare. All’interno saranno quindi presenti informazioni, tecniche, spunti e trucchi per i pi∙ esperti ed una serie di riferimenti comparativi per i programmatori C++. Nella prima parte di articoli ci limiteremo a descrivere le basi del linguaggio e delle classi. Nella seconda svilupperemo insieme una vera e propria applicazione in Java. Inoltre, sarα dato spazio a classi, tecniche ed altre informazioni di particolare interesse sviluppate dai lettori. A quanti non hanno letto i due servizi d’apertura, ricordiamo che essi sono stati dedicati alla sintassi del linguaggio, cioΦ a quelle istruzioni che costituiscono la struttura portante del programma. L’acquisizione della grammatica base di un linguaggio non Φ tuttavia sufficiente a sviluppare applicazioni complesse. Per sfruttare a pieno le potenzialitα di un linguaggio Φ necessario utilizzare quelle classi e quei metodi che permettono di accedere alle risorse fisiche del sistema, alle funzioni del sistema operativo ed ai protocolli di rete. Questo sarα il tema delle puntate successive. Tenete inoltre presente che Java Φ un linguaggio in continua evoluzione, per cui Φ importante fare sempre riferimento ai vari aggiornamenti allo standard reperibili dal sito della Sun. Innanzitutto cos’∞ Java. ╔ un linguaggio fortemente orientato agli oggetti. Questo vuol dire che il modo di programmare in Java Φ quello di definire classi di oggetti che interagiscono fra di loro. Potete immaginare un programma Java come una scatola in cui galleggiano a gravitα zero biglie di tutte le forme e dimensioni. Se immettete dall’esterno una nuova biglia o comunque urtate una di quelle giα esistenti, darete origine a tutta una serie di urti e quindi di eventi il cui risultato potrebbe essere ad esempio rappresentato dall’uscita di un’altra biglia dalla scatola stessa. Un linguaggio orientato agli oggetti opera proprio cos∞. Avete un certo numero di oggetti che possono interagire fra loro. La creazione di un nuovo oggetto od un evento che arriva dall’esterno del programma scatena una serie di reazioni che producono altri oggetti ed altri eventi. Un evento pu≥ essere, per esempio, la pressione di un pulsante su un’interfaccia grafica o l’arrivo di un segnale dalla rete. Nei linguaggi procedurali si procedeva, invece, secondo una logica ad azioni sequenziali o parallele. Prima faccio questo, poi quello, quindi attivo altre due sequenze che in parallelo compiono altre azioni, mi metto in attesa finchΘ non hanno finito ed infine attivo una sequenza conclusiva di azioni. Nel C++, che non Φ un linguaggio orientato agli oggetti puro, ma una sorta di potente ibrido fra un macro assemblatore ed un linguaggio ad oggetti, un’applicazione ha comunque una funzione iniziale chiamata main. In Java non esistono funzioni, ma solo metodi appartenenti ad una ben specifica classe. Il punto d’ingresso di un’applicazione Φ quindi un metodo, per coerenza ancora chiamato main, che viene eseguito automaticamente quando si passa all’interprete Java il nome di una classe in cui esso sia stato definito.

Classe, metodi, oggetti

Veniamo ora alla terminologia usata. Abbiamo parlato di classi, metodi ed oggetti. Vediamo rapidamente cosa sono. Una classe Φ una definizione di dati e di funzioni che operano sugli stessi. Ad esempio, una classe Stringa pu≥ essere definita come un vettore di N caratteri qualunque, un intero che ne indica la lunghezza, ed una serie di funzioni che operano su questi dati: un metodo per invertire la stringa, uno che ne ritorna la lunghezza, uno che cerca all’interno della stringa un’altra stringa data o che conta il numero di volte che essa si presenta, e via dicendo. Da notare che in genere Φ buona pratica nascondere i dati dell’oggetto permettendone l’accesso solo attraverso un metodo. Per esempio, se lunghezza Φ l’intero che contiene la lunghezza della stringa, tale informazione sarα disponibile utilizzando un metodo lunghezza () che ritorna quel valore, piuttosto che accedere direttamente al valore stesso. Il motivo Φ che altrimenti si potrebbe correre il rischio che un programma modifichi alcuni dati dell’oggetto facendone perdere la coerenza. Per esempio, potrei impostare la lunghezza di "Pippo" a sette, invece che a cinque, lasciando contemporaneamente inalterata la vera lunghezza della stringa. Un metodo Φ quindi una funzione interna alla classe che opera sui dati della stessa. Un oggetto Φ l’istanza di una classe, cioΦ la sua materializzazione in termini di codice. Se uomo Φ una classe, Carlo ed Andrea sono oggetti. Essi, infatti, sono entrambi uomini e condividono la stessa struttura dei dati; hanno, per esempio, entrambi un’etα, ma il valore dei dati pu≥ essere differente. Andrea ha 15 anni, Carlo 76. Parimenti sia mioNome sia mioCognome possono essere oggetti della classe Stringa, ma il loro contenuto Φ ovviamente differente. Detto questo passiamo al linguaggio. Anche se questa parte della trattazione Φ prevalentemente dedicata ai principianti, le tabelle proposte sono strutturate come un’utile guida di riferimento rapida anche per gli esperti. Potete fotocopiarle e tenerle accanto al computer mentre programmate.

I programmi possono essere scritti sia in Unicode sia in un qualunque insieme di caratteri di tipo ASCII esteso che possa essere convertito in Unicode. Questo sistema Φ uno schema di codifica dei caratteri basato su due byte che permette di rappresentare fino a 34.168 caratteri differenti, tra cui quelli appartenenti all’alfabeto greco, russo, giapponese, ebraico, arabo e via dicendo. Questo, se da un lato permette di scrivere codice nella propria lingua nativa, dall’altro pu≥ tuttavia creare problemi qualora si volesse distribuire il sorgente ad altri sviluppatori di nazioni diverse o che lavorano su differenti piattaforme. Infatti, sebbene qualunque implementazione di Java accetti il sorgente in Unicode, la maggior parte degli editori disponibili nei vari sistemi operativi continua a supportare solo un limitato insieme di caratteri generalmente basato sul vecchio sistema ASCII.

Programmazione e parole chiave

Un linguaggio di programmazione Φ formato da una serie di simboli, identificatori e parole chiave che vanno assemblati secondo certe regole, che formano la sintassi del linguaggio. Le parole chiave sono definite dal linguaggio, hanno un significato ben preciso e non possono essere modificate. In Tabella 1 Φ riportata la lista di tutte le parole chiave di Java. Non Φ permesso usarle come nomi di variabili od altri elementi del programma quali metodi, costanti e cos∞ via. Le parole chiave riportate in corsivo in tabella sono riservate, ma non pi∙ di uso corrente. Come abbiamo giα accennato, infatti, il linguaggio Java Φ in continua evoluzione, anche se Sun, caso unico nella storia, ha proposto la candidatura di Java quale standard internazionale. Θ la prima volta che uno standard Φ stato sottomesso all’ISO da un’azienda privata piuttosto che da un consorzio o da un’organizzazione internazionale. Gli identificatori, viceversa, sono definiti dal programmatore e seguono una ben precisa nomenclatura che dipende solitamente dall’elemento identificato. Un identificatore deve sempre iniziare con una lettera oppure con i simboli del dollaro o del trattino di sottolineatura. Il resto del nome pu≥ contenere sia tali caratteri sia numeri. Per lettera, tuttavia, oltre ai classici caratteri dell’alfabeto anglosassone maiuscoli e minuscoli, valgono tutti i caratteri Unicode al di sopra del valore 0x00C0. A parte questo, l’unico altro obbligo nel definire un identificatore Φ quello di non utilizzare una parola riservata al linguaggio, e cioΦ le parole chiave giα viste pi∙ le due stringhe booleane true e false. Per convenzione, anche se non Φ obbligatorio, i nomi delle variabili iniziano con una lettera minuscola, quelli delle classi con una lettera maiuscola. Java rispetta la cassa dei caratteri come il C ed il C++. Il nome pippo Φ quindi differente da Pippo. Esistono poi cinque differenti tipi di costanti esplicite, o literal: gli interi in base 8, 10 o 16, come in C (8, 16, 32 e 64 bit), i valori reali in formato IEE 754 a singola e doppia precisione, i booleani true e false, i caratteri e le stringhe. Da notare che in Java i booleani non sono di tipo numerico, per cui non esiste la conversione implicita fra interi e booleani come in C e C++. I simboli sono di due tipi: operatori e separatori. Ci sono quattro gruppi di operatori, riportati nelle tabelle dalla 2 alla 9. Gli operatori possono essere unari o binari. Quelli unari a loro volta possono essere del tipo suffisso, cioΦ posizionati dopo l’operando, o del tipo prefisso, cioΦ posizionati davanti all’operando. Lo stesso simbolo pu≥ tuttavia rappresentare operatori differenti. Per esempio, il segno meno, utilizzato come operatore unario, pu≥ essere posto solo davanti al numero, utilizzato come operatore binario, va posto tra i due operandi. Analogamente, l’operatore ++ pu≥ essere posto sia davanti sia dopo l’operando, ma il significato Φ decisamente differente. Rispetto al C++, esiste un ulteriore operatore di scorrimento identificato dal simbolo >>> che riempie con zeri a sinistra il valore man mano che scorre a destra. Esso Φ necessario in quanto tutti gli interi in Java sono valutati con segno, non esistono, cioΦ, gli interi unsigned come in C e C++. I separatori sono quei simboli, quali le parentesi, che rappresentano la punteggiatura del linguaggio. Essi sono riportati nella Tabella 10. Esistono tre tipi di commenti. Quelli classici, analoghi a quelli usati in C e racchiusi fra /* e */, quelli di linea, tipici del C++, e che iniziano sempre con // e terminano alla fine della linea, e quelli per la generazione automatica della documentazione, racchiusi fra il simbolo /** ed il simbolo */. Un programma Java Φ formato da una o pi∙ definizioni di classi. Ogni classe contiene un certo numero di dati e di metodi. Ogni metodo Φ una funzione che opera sui dati interni della classe, e quelli passati al metodo come parametri. L’insieme dei valori che in un certo momento assumono tutti i dati di un oggetto di una certa classe, sono detti stato dell’oggetto. Al contrario del C++, dove la dichiarazione di una classe, fatta generalmente in un file con estensione h, hxx o hpp, era qualcosa di ben distinto dalla definizione della stessa, riportata in un file di tipo c, cxx o cpp, in Java le dichiarazioni vengono fatte contestualmente all’implementazione e sono entrambe riportate nello stesso file, la cui estensione Φ sempre Java. Esso Φ, infatti, un interprete: le istruzioni, benchΘ trascritte in un formato intermedio, vengono lette ed eseguite una per una cos∞ come sono state scritte, per cui non possono essere accettate strutture che non possano essere risolte al momento dell’esecuzione (run-time). Un linguaggio compilato, invece, tramite i passi di compilazione e risoluzione dei collegamenti (compile e link), pu≥ accettare una sintassi pi∙ complessa che prevede, per esempio, le dichiarazioni anticipate o collegamenti non risolti fin dall’inizio. Stiamo forse per≥ entrando troppo in dettagli che non sono essenziali a sviluppare un programma in Java. Ritorneremo eventualmente in seguito sull’argomento.

Le istruzioni

Le istruzioni in Java sono di tre tipi: dichiarazioni, espressioni e istruzioni di controllo del flusso. Le dichiarazioni sono utilizzate per definire le proprietα di una classe, di un metodo, di una variabile, di una costante e cos∞ via. La loro sintassi dipende da cosa stiamo dichiarando e la vedremo volta per volta quando andremo ad analizzare in dettaglio i vari elementi del linguaggio. Le espressioni sono una combinazioni di variabili, costanti esplicite e non, operatori e chiamate a metodi il cui risultato Φ un valore ben definito. Espressioni sono, per esempio, la chiamata ad un metodo, come System.in.read(), operazioni su variabili, come index++ oppure operazioni aritmetiche come a*(b-c). Il valore dell’espressione pu˜ essere assegnato ad una variabile utilizzando uno degli operatori di assegnazione (Tabella 9). Nel prossimo numero, descriveremo le istruzioni di controllo del flusso ed inizieremo a vedere i vari tipi di dichiarazioni e la differenza fra tipi e classi. Per il momento╔auguri.

(ddejudicibus@tecnet.it)

 

 

Tabella 1. Parole chiave
Abstract Double int static
Boolean Else interface super
Break Extends long switch
Byte Final native synchronized
Case Finally new this
Catch Float null throw
Char For package throws
Class Goto private transient
Const If protected try
Continue Implements public void
Default Import return volatile
Do Instanceof short while

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Tabella 2. Operatori aritmetici unari

Operatore

Utilizzo

Descrizione

+

+ n

Valore positivo

-

- n

Nega il valore di n

++

n ++

Incrementa n di 1, ritorna il valore originale

++

++ n

Incrementa n di 1, ritorna il valore modificato

--

n --

Riduce n di 1, ritorna il valore originale

--

-- n

Riduce n di 1, ritorna il valore modificato

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 







Tabella 3.
Operatori aritmetici binari

Operatore

Utilizzo

Descrizione

+

n + m

Somma n ed m

-

n - m

Sottrae m da n

*

n * m

Moltiplica n per m

/

n / m

Divide n per m

%

n % m

Ritorna il resto di n diviso per m

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 







Tabella 4.
Operatori relazionali

Operatore

Utilizzo

La condizione Φ vera se...

>

n > m

N Φ maggiore di m

>=

n >= m

N Φ maggiore od uguale ad m

<

n < m

N Φ minore di m

<=

n <= m

N Φ minore od uguale ad m

==

n == m

N Φ uguale ad m

!=

n != m

N Φ diverso da m

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 




Tabella 5.
Operatori condizionali

Operatore

Utilizzo

La condizione Φ vera se...

&&

n && m

Sia n che m sono veri

||

n || m

Uno qualunque dei due operandi Φ vero

!

! n

N Φ falso

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Tabella 6. Operatori condizionali ternari

Operatore

Utilizzo

Significato

? :

n ? a : b

Se n Φ vero ritorna a, altrimenti ritorna b

 

 

 

 

 

 

 


Tabella 7. Operatori di scorrimento

Operatore

Utilizzo

Sposta i bit di n...

>>

n >> m

A destra di m posizioni

<<

n << m

A sinistra di m posizioni

>>>

n >>> m

A destra di m posizioni (unsigned)

 

 

 

 

 

 

 

 

 

 

 






Tabella 8. Operatori aritmetici sui Bit

Operatore

Utilizzo

Descrizione

&

n && m

N AND m

|

n || m

N OR m

^

! n

N XOR m

~

~ n

NOT n

 

 

 

 

 

 

 

 

 

 










Tabella 9. Operatori di asseganzioni

Operatore

Utilizzo

Operazione equivalente

=

n = m

Assegna il valore di m ad n

+=

n += m

N = n + m

-=

n -= m

N = n – m

*=

n *= m

N = n * m

/=

n /= m

N = n / m

%=

n %= m

N = n % m

&=

n &= m

N = n & m

|=

n |= m

N = n | m

^=

n ^= m

N = n ^ m

>>=

n >>= m

N = n >> m

<<=

n <<= m

N = n << m

>>>=

n >>>= m

N = n >>> m




































 

 

 

 

 

 

 

 

 













Tabella 10. Separatoroi

Separatore

Utilizzo

{ }

Blocco di istruzioni

[ ]

Vettori e matrici

( )

Operazioni aritmetiche, parametri, condizioni

.

Composizione degli identificatori

;

Fine istruzione

" "

Stringa letterale

,

Separatore nelle liste




Internet News Φ un mensile della Casa Editrice Tecniche Nuove S.p.A.
⌐ 1995/96/97. Tutti i diritti sono riservati.
Internet News non risponde di eventuali errori e omissioni.
Commenti a: inews@tecnet.it