3. Il Linguaggio Java
Green
group
Nel 1991 alla SUN Microsystem viene sviluppato il linguaggio OAK come
parte di un progetto destinato all’elettronica di consumo (televisori,
videoregistratori, tostapane, ecc.).
OAK non suscitò nessun interesse fino a quando, accantonata l’idea
dell’elettronica di consumo, il progetto non venne indirizzato verso Internet.
Nel 1994-1995 dall’esperienza di OAK nacque Java (il nome fu cambiato per
problemi di copyright).
Venne quindi presentato il web browser HotJava in grado di eseguire le
applicazioni Java, dette applet, riferite all’interno delle pagine HTML.
Netscape fu il primo web browser a includere in Navigator 2.0 il supporto per
l’esecuzione delle applet Java e con la diffusione di Internet Java e le applet
divennero sempre più popolari.
3
Dispense su JAVA
4. Caratteristiche Fondamentali di Java
Le caratteristiche fondamentali di Java sono le seguenti:
è un linguaggio orientato a oggetti
è relativamente più semplice di altri linguaggi orientati a oggetti come il C++
ha estese funzionalità di rete
è un linguaggio interpretato, ma esistono i compilatori JIT
un compilatore Just-In-Time compila una sola volta il bytecode in codice
macchina nativo e lo inserisce in una memoria cache in modo che le
successive esecuzioni siano più veloci
è robusto
è sicuro
è portabile
è dinamico, le classi di un applicazione vengono ricercate dinamicamente a run-
time quando vengono riferite
consente di realizzare applicazioni scalabili eseguibili dai telefoni cellulari ai
server.
4
Dispense su JAVA
5. I Kit di Sviluppo per Java
Le versioni di Java corrispondono alle versioni del jdk, il Java Development
Kit, che contiene l’ambiente di sviluppo per Java.
Le versioni Java rilasciate sono state: jdk 1.0, jdk 1.1 e jdk 1.2, quest’ultima
versione è stata denominata Java 2.
La versione corrente di Java è il jdk 1.4, mentre il jdk 1.5 è in versione beta.
Diverse funzionalità sono state aggiunte nelle varie versioni. Ciò comporta
che i programmi per le vecchie versioni funzionano in quelle nuove, ma non è
vero il contrario.
Sul mercato sono presenti molti ambienti di sviluppo integrati quali:
VisualAge IBM
VisualCafé Symantec
JBuilder Borland
Fortè SUN 5
Dispense su JAVA
7. Java 2 SDK, Standard Edition v. 1.3
Java Applications Java Applets
7
Dispense su JAVA
8. Java è un linguaggio interpretato
file
Sorgente
La compilazione dei file sorgenti Java
.java
java crea dei file contenenti il
bytecode, cioè un insieme di
istruzioni simili al linguaggio
macchina, ma indipendenti dal Compilatore
processore. Java
Per eseguire il bytecode è
necessario un interprete, la Java Java file
Virtual Machine (JVM), dipendente Bytecode .class
dal processore.
JVM
JVM JVM
JVM JVM
JVM
per
per per
per per
per
Linux
Linux Solaris
Solaris Windows
Windows
Linux OS
Linux OS Solaris OS
Solaris OS Windows OS
Windows OS
8
Dispense su JAVA
9. Esempio di Bytecode
Un file di bytecode è praticamente
illeggibile perché è costituito da una
sequenza di caratteri in formato
Unicode.
Un editor visualizzerebbe il
bytecode come riportato nell’imma-
gine, non riuscendo a tradurre il
bytecode in codice ASCII.
Il bytecode contiene tutte le
informazioni che descrivono le
classi.
È possibile pertanto ricostruire con
opportuni tool il codice sorgente del
programma a partire dal bytecode
9
Dispense su JAVA
10. Java è un Linguaggio Robusto
Java fornisce:
un forte controllo dei tipi
la gestione delle eccezioni
il controllo dei puntatori nulli
il controllo nei limiti degli indici degli array.
In particolare, la gestione delle eccezioni1 obbliga il programmatore a gestire
situazioni anomale che altrimenti potrebbero causare il crash di un
programma.
1 Un’eccezione è un evento, generato a run-time, che deve essere opportunamente
gestito dal programma.
10
Dispense su JAVA
11. Java è un Linguaggio Sicuro
Un programma Java, detta applet1, può essere eseguito come conseguenza
di una connessione web tramite una pagina HTML, senza alcuna possibilità di
controllo da parte dell’utilizzatore del web browser.
Il verificatore del bytecode della Java Virtual Machine controlla che nell’applet:
non ci sia codice che violi la sicurezza del sistema
non ci sia codice che forzi i puntatori
non ci siano violazioni sui diritti di accesso a oggetti.
Inoltre, una applet può aprire una connessione solo con l’host dal quale è
stata scaricata, rendendo impossibile la connessione con host sconosciuti e
non desiderati.
1 Un applet è un’applicazioni Java riferita in una pagina HTML ed eseguita, dopo il
suo caricamento, dalla Java Virtual Machine del web browser. 11
Dispense su JAVA
12. Java è un Linguaggio Portabile
Il bytecode generato dai compilatori delle diverse piattaforme è eseguibile da
tutte le Java Virtual Machine (write-once-run-everywhere).
Oltre alla portabilità del bytecode, esiste la portabilità a livello di programma
sorgente:
le API1 non cambiano al variare del sistema
l’insieme di caratteri Unicode consente di esprimere i simboli delle lingue di tutto il
mondo
il numero di byte utilizzati per i diversi tipi è lo stesso per tutte le piattaforme.
è garantito che gli operandi siano valutati da destra a sinistra.
1 API: Application Programmer Interface.
12
Dispense su JAVA
13. Java è un Linguaggio Multithread
I thread, detti anche processi leggeri, consentono di eseguire attività
concorrenti interne a un processo schedulato dal sistema operativo.
A ogni thread è associato un flusso di esecuzione indipendente all’interno
dello stesso processo.
Il cambio di contesto tra thread ha un basso overhead in quanto i thread
condividono lo stesso spazio di indirizzi del programma.
Possibili impieghi dei thread:
eseguire algoritmi intrinsecamente concorrenti
rendere l’interfaccia grafica più reattiva
utilizzare il parallelismo reale dei sistemi multiprocessore
l’esecuzione di un numero variabile e non noto a priori di richieste di servizio
eseguire lunghe operazioni di I/O mentre l’elaborazione avanza.
13
Dispense su JAVA
16. Struttura di un Programma Java
Java è un linguaggio orientato a oggetti e pertanto un programma Java è
costituito da istanze di una o più classi.
Ogni classe pubblica deve essere contenuta in un file separato avente lo
stesso identificatore della classe e con estensione java (idClasse.java).
Una o più classi pubbliche possono contenere il metodo main() strutturato
nel seguente modo:
...
public static void main(String[] args) {
...
}
...
Per eseguire un programma si invoca l’interprete Java fornendogli come
argomento l’identificatore di una classe che contiene il metodo main().
L’interprete esegue il metodo main() fino alla sua terminazione, naturale o
forzata. 16
Dispense su JAVA
17. Struttura di un File Sorgente Java
// opzionale – definizione di un package se omesso le definizioni
package IdPackage; appartengono al package di default
// zero o più – package importati
import java.util.*;
// una per file – definizione di una classe public
public class IdClassePubb {
// zero o uno – metodo main()
a public static void main(String[] args) {
...
} // end main
...
} // end IdClassePubb
// zero o più – definizione di classe non pubblica
class IdClassePriv {
...
} // end IdClassePriv
17
Dispense su JAVA
18. Un Semplice Programma Java
Il programma stampa i parametri passati sulla linea di comando.
il metodo main() deve avere come
il nome del file deve unico parametro un array di stringhe,
coincidere con il nome la cui lunghezza è data (come per
della classe che contiene ogni array) da argv.length
il metodo main()
Echo.java
public class Echo {
public static void main(String[] args) { ciclo che stampa i
parametri passati
for (int i = 0; i < args.length; i++) sulla linea di comando
System.out.print(args[i] + " ");
stampa una
System.out.println(); linea vuota
System.exit(0);
}
}
System.exit() provoca l’uscita
dall’interprete e la terminazione
del programma restituendo
18
Dispense su JAVA
l’intero 0
19. Compilazione ed Esecuzione
compilazione
prompt >
prompt > javac Echo.java
prompt > Echo.java Echo.class
javac
programma bytecode
sorgente Java
esecuzione
prompt >
prompt > java Echo uno due tre Echo.class memoria
uno due tre processo
prompt > java
bytecode
19
Dispense su JAVA
20. Esempio di Programma Java
Esempio.java
public class Esempio { creazione di un array
public static void main (String args[]) {
int tot = 0; length è un attributo
int lung[] = new int[args.length]; degli oggetti array
System.out.println("Ci sono " + args.length + " parametri:");
for (int i = 0; i < args.length; i++) {
lung[i] = args[i].length(); length() è un metodo
tot = tot + lung[i]; della classe String
System.out.println("- Il parametro " + args[i] +
" e' lungo " + lung[i] + " caratteri");
}
System.out.println("In totale ci sono " + tot + " caratteri.");
}
}
20
Dispense su JAVA
21. Struttura di un’Applicazione Java (1)
Un’applicazione Java solitamente è costituita da più classi in relazione.
Le classi sono a loro volta organizzate in package, che è il costrutto di
modularizzazione di Java, anche per consentire opportuni livelli di visibilità
delle classi stesse, dei loro attributi e delle loro operazioni.
Un’applicazione Java non ha dati globali, ma locali a ciascuna istanza.
L’interazione avviene fra le istanze mediante lo scambio di messaggi.
21
Dispense su JAVA
22. Struttura di un’Applicazione Java (2)
classe
relazione
package in Java
(ce ne sono di diversi tipi)
22
Dispense su JAVA
25. Commenti
Il compilatore Java riconosce tre tipi di commenti:
/* commento */
commento tradizionale: tutti i caratteri compresi tra /* e */ vengono ignorati, come nei
linguaggi C e C++
// commento
commento di una linea: tutti i caratteri compresi tra // e la fine della linea vengono
ignorati, come nel linguaggio C++
/** commento */
commento di documentazione che va posto immediatamente sopra una dichiarazione
(di variabile o metodo)
il testo compreso tra /** e */ può essere processato da un programma separato
(javadoc) che produce automaticamente la documentazione del programma in formato
HTML.
25
Dispense su JAVA
26. Uso dei Commenti per Generare la
Documentazione con javadoc (1)
ProgArgs.java
/**
Una istanza della classe ProgArgs e' utilizzata
per gestire gli argomenti passati a un programma:
memorizzarli, restituirli, stamparli.
@author Pinco Palla
@version 1.0
*/
public class ProgArgs {
/**
Memorizza gli argomenti passati al programma
@param args array di stringhe passate al programma
*/
public ProgArgs(String args[]) {
argsList = new String[args.length];
for(int i = 0; i < args.length; i++)
argsList[i] = args[i];
}
...
26
Dispense su JAVA
27. Uso dei Commenti per Generare la
Documentazione con javadoc (2)
ProgArgs.java
...
/**
Restituisce una copia degli argomenti passati
al programma in un array di stringhe
@return restituisce la lista degli argomenti
passati al programma attraverso un array di stringhe
*/
public String[] getArgs() {
String[] argsTemp = new String[argsList.length];
for(int i = 0; i < argsList.length; i++)
argsTemp[i] = argsList[i];
return argsTemp;
}
/**
Stampa gli argomenti passati al programma
*/
public void printArgs() {
for(int i = 0; i < argsList.length; i++)
System.out.print(argsList[i] + " ");
System.out.println();
}
/**
array che memorizza gli argomenti passati al programma
*/
String argsList[];
}
27
Dispense su JAVA
28. Generazione della
Documentazione con il Tool javadoc
directory di
destinazione
utility che genera
la documentazione
in formato HTML
28
Dispense su JAVA
33. Identificatori
Un identificatore è un nome usato in un programma per identificare:
variabili/istanze
nomi di metodi
nomi di classi
...
Un identificatore è una sequenza di caratteri (lettere e cifre) senza limiti di
lunghezza, che inizia con una lettera, underscore o dollaro
lettere: A-Z, a-z, _, $.
Due identificatori sono uguali se coincidono esattamente in base al codice
Unicode
due identificatori apparentemente simili potrebbero invece differire, in quanto:
u0061 = ‘a’, u0041 = ‘A’, u0430 = cyrillic ‘a’.
33
Dispense su JAVA
34. Le Parole Chiave di Java
Una parola chiave è una sequenze di caratteri che non può essere usata
come identificatore perché ha uno speciale significato per il linguaggio.
Le parole chiave di Java sono le seguenti:
abstract
abstract default
default if
if private
private this
this
boolean
boolean do
do implements
implements protected
protected throw
throw
break
break double
double import
import public
public throws
throws
byte
byte else
else instanceof
instanceof return
return transient
transient
case
case extends
extends int
int short
short try
try
catch
catch final
final interface
interface static
static void
void
char
char finally
finally long
long strictfp
strictfp volatile
volatile
class
class float
float native
native super
super while
while
const
const for
for new
new switch
switch
continue
continue goto
goto package
package synchronized
synchronized
NOTE: - le parole chiave const e goto non sono utilizzate
- true e false sono parole riservate (sono dei literal boolean)
- null è una parola riservata (è un literal nullo) 34
Dispense su JAVA
35. I Tipi
Un tipo determina i valori che una variabile può assumere e le operazioni
valide applicabili sui valori.
Ci sono due categorie di tipi:
tipi primitivi
numeri interi (byte, short, int, long)
reali (float, double)
charatteri (char)
booleani (boolean)
tipi reference
puntatori ad oggetti (classi) e puntatori ad array
Il formato e la dimensione dei tipi di dati è garantito essere lo stesso su ogni
JVM, indipendentemente dalla sua implementazione interna e quindi dalla
piattaforma hardware su cui viene eseguita.
35
Dispense su JAVA
36. Assenza in Java del Tipo Puntatore
Nel linguaggio Java non esiste il tipo puntatore, cioè un tipo che fa riferimento
a un valore in modo indiretto.
In realtà, tranne che per le variabili di tipo primitivo (tipi interi, reali, boolean e
caratteri), durante la dichiarazione viene allocato un riferimento che non punta
a nessuna zona di memoria fin quando non viene allocata esplicitamente con
l’operatore new.
Quindi il concetto di allocazione dinamica esiste in Java; non esiste
l’aritmetica dei puntatori e non sono possibili tutte le manipolazioni dei
puntatori così come sono consentite in C o C++.
36
Dispense su JAVA
37. Variabili (1)
Una variabile è un identificatore di una locazione di memoria a cui é associato
un tipo di dato (un tipo primitivo o un riferimento a un tipo di dato).
Una variabile contiene sempre un dato compatibile con il tipo a cui è stata
associata all’atto della dichiarazione.
Il valore della variabile cambia in seguito ad assegnamenti o tramite operatori
di incremento/decremento (++ o --).
Tutti i tipi di dato hanno un valore di default per l’inizializzazione delle variabili
dichiarate nelle classi: 0, null=u0000, false.
Le variabili dichiarate in un qualunque blocco, { ... }, prima di essere
utilizzate devono essere esplicitamente inizializzate.
37
Dispense su JAVA
38. Variabili (2)
Il linguaggio Java ha tre tipi di variabili:
variabili di istanza (dette anche campi)
vengono dichiarate nel contesto di una classe e sono allocate per ogni istanza della
classe
variabili di classe
vengono dichiarate static nel contesto di una classe e sono allocate una sola volte e
condivise fra tutte le istanze della stessa classe
variabili locali ai metodi
vengono dichiarate nei metodi delle classi.
38
Dispense su JAVA
39. Dichiarazione e Definizione di Variabili
Dichiarare una variabile vuol dire associarle un tipo e quindi allocarla in
memoria.
Definire una variabile vuol dire dichiararla e contestualmente inizializzarla,
cioè associarle un valore iniziale.
L’assegnamento di una variabile è l’associazione di un valore dopo la sua
inizializzazione.
In Java, una variabile può essere dichiarata e/o definita in qualunque blocco,
{ ... }, all’interno del codice.
...
boolean cond; // dichiarazione
int i = 0; // dichiarazione e definizione
cond = true; // assegnamento
i++; // assegnamento
...
39
Dispense su JAVA
40. Esempi di Dichiarazioni di Variabili
La generica dichiarazione ha la seguente forma:
int count;
Tipo identificatore
della variabile
Dichiarazioni con inizializzazione:
char c = ’a’;
String txt = ”testo”;
Valore
iniziale
40
Dispense su JAVA
41. Dichiarazioni di Variabili non Primitive
Nel caso di variabili di tipo non primitivo, array e istanze di classi, bisogna
compiere due azioni:
dichiarazione dell’istanza o dell’array
creazione dinamica dell’istanza o dell’array con l’operatore new.
Le due azioni possono essere effettuate contestualmente oppure con due
istruzioni distinte:
...
class A {
...
}
...
int p = 10; // variabile dichiarata e definita
A ia; // istanza dichiarata, ma non allocata
ia = new A(); // allocazione dell’istanza
int[] n = new int[p]; // dichiarazione e allocazione di un array
int m[] = new int[p]; // dichiarazione e allocazione di un array
...
41
Dispense su JAVA
42. Valori di Default
delle Variabili di un Tipo Primitivo
Nessuna istanza di variabile o elemento
di array può avere un valore indefinito, Tipo Valore default
Java assegna, alla dichiarazione, i byte 0
seguenti valori di default
short 0
int 0
long 0L o 0l
float 0.0F o 0.0f
double 0.0D o 0.0d
char ‘u0000’ (null)
boolean false
tipi reference null
42
Dispense su JAVA
43. Zona di Influenza e
di Visibilità delle Variabili
La zona di influenza di una variabile è delimitata dal blocco in cui la variabile
è valida (zona compresa fra l’istruzione di allocazione e quella di
deallocazione).
Un blocco è delimitato da una parentesi graffa aperta ({) e dalla
corrispondente parentesi graffa di chiusura (}).
La zona di visibilità di una variabile è quella in cui è possibile utilizzare la
variabile.
La zona di visibilità è sempre minore o uguale a quella di influenza.
In Java le variabili possono essere allocate in qualunque punto di un blocco e
una variabile può nascondere una variabile, avente lo stesso identificatore e
lo stesso tipo, dichiarata in un blocco di livello superiore.
43
Dispense su JAVA
44. Esempi di Zona
di Influenza e di Visibilità Input.java
public class Scope {
public static void main(String argv[] ) {
Scope ie = new Scope();
zona di ie.f();
visibilità }
di p’
public void f() {
zona di
influenza System.out.println(p);
di p’ e di
c int p = 10; // un’altra variabile p (p’’)
{
zona di zona di int p; // ERRORE – variab. gia’ dichiarata
visibilità influenza int t = 10; // variabile t (t’)
di c e di System.out.println(p);
zona di influenza p = 20;
visibilità e di visibilità di t’
di p’’ System.out.println(p);
}
int t = 4; // un’altra variabile t (t’’)
zona di influenza p = t;
e di visibilità di t’’
}
zona di private char c = 'a';
visibilità di p’ private int p = 5; // variabile p (p’)
}
44
Dispense su JAVA
45. I Literal
Un literal denota un valore costante appartenente a un tipo.
Esempi:
literal boolean literal esadecimali (iniziano con 0x)
true, false 0x0 0x1a1f 0xab3d 0x6D9F
literal nullo literal ottali (iniziano con 0)
null 00 0567 0777
literal char literal floating point (float, double)
(default double)
'a' 't‘ ‘’ ''' 'uFFFF'
3.5 5E-1 -4.5
literal String
...
"" """ "testo“
literal interi (int, long)
(default int)
5 10 -20 5L 10L -15L
45
Dispense su JAVA
46. I Tipi Interi e Reali
I tipi interi nelle varie precisioni sono i seguenti:
byte (8 bit) valori da -128 a 127 (-27 – 27 – 1)
short (16 bit) valori da -32768 a 32767 (-215 – 215 – 1)
int (32 bit) valori da -2147483648 a 2147483647 (-231 – 231 – 1)
long (64 bit) valori da -9223372036854775808 a 9223372036854775807
(-263 – 263 – 1)
In Java non esistono tipi senza segno che possono assumere solo valori
positivi (unsigned).
I tipi reali nelle varie precisioni sono i seguenti:
float (32 bit) valori da 32-bit floating point (6-7 cifre decimali significative)
MIN: 1.40129846432481707e-45 MAX: 3.40282346638528860e+38
double (64 bit) valori da 64-bit floating point (15 cifre decimali significative)
MIN: 4.94065645841246544e-324 MAX: 1.79769313486231570e+308
46
Dispense su JAVA
47. I Tipi Primitivi Java
tipi primitivi
tipo boolean tipi numerici
tipi integrali tipi floating point
boolean
tipo carattere tipi interi
float double
char byte short int long
classi wrapper
boolean Boolean char Character int Integer float Float
byte Byte short Short long Long double Double47
Dispense su JAVA
48. Il Tipo Carattere
Il tipo carattere, char, occupa 16 bit e memorizza un intero senza segno
(positivo) corrispondente al codice Unicode del carattere.
I valori possibili per il tipo char vanno:
II programmi Java sono scritti utilizzando
programmi Java sono scritti utilizzando
da 0 ( = u0000 ) a 65535 ( = uffff ) il set di caratteri Unicode 2.0.
il set di caratteri Unicode 2.0.
Tutti ii caratteri vengono convertiti in
Tutti caratteri vengono convertiti in
La dichiarazione: formato Unicode: uXXXX
formato Unicode: uXXXX
char c = ’A’; dove XXXX è il numero esadecimale
dove XXXX è il numero esadecimale
corrispondente al codice ASCII
corrispondente al codice ASCII
equivale alle due linee: II primi 128 caratteri Unicode corrispon-
primi 128 caratteri Unicode corrispon-
dono ai caratteri ASCII.
dono ai caratteri ASCII.
char c; // c = null
c = ’A’; // assegnamento
48
Dispense su JAVA
49. Caratteri Speciali
codice
carattere unicode significato
b
b u0008
u0008 backspace BS
backspace BS
t
t u0009
u0009 horizontal tab HT
horizontal tab HT
n
n u000a
u000a linefeed LF
linefeed LF
f
f u000c
u000c form feed F
form feed F
r
r u000d
u000d carriage return C
carriage return C
"
" u0022
u0022 double quote “
double quote “
'
' u0027
u0027 single quote ‘
single quote ‘
u005c
u005c backslash
backslash
...
System.out.println(”Primo:ntSecondo”); produce Primo:
... come output Secondo
49
Dispense su JAVA
50. Array (1)
Dichiarazione e allocazione di un array, sono due azioni distinte
dichiarazione
specifica del nome della variabile di tipo reference
allocazione
allocazione in memoria dello spazio necessario, inizializzazione di tutti gli elementi e
assegnamento dell’indirizzo alla variabile reference
Dichiarazione di array
...
char s[];
int [] array;
int xx[][]; // matrice a due dimensioni
int [] x, yy[]; // equivale alla seguente
int x[], yy[][]; // equivale alla precedente
...
50
Dispense su JAVA
51. Array (2)
La creazione (allocazione memoria) avviene attraverso l’operatore new:
...
char s[];
int [] array;
int xx[][]; // matrice a due dimensioni
int [] x, yy[]; // equivale alla seguente
int x[], yy[][]; // equivale alla precedente
array = new int[10];
yy = new int [3][4];
...
51
Dispense su JAVA
52. Array (3)
Creare un array di oggetti non significa creare gli elementi dell’array.
Gli array di oggetti, ad esempio String e gli oggetti definiti dall’utente, essendo
di tipo reference, vengono inizializzati con il valore null.
... 0 1 2 3
String [] nomi = new String[4]; null null null null
...
Quando verranno creati i singoli oggetti gli elementi dell’array avranno valori
significativi.
0 1 2 3
...
null null null
nomi[1] = ”xyz”;
...
”xyz”
52
Dispense su JAVA
53. Array (4)
Creazione ed inizializzazione di array:
...
int pot [] = {1, 2, 4, 8, 16, 32, 64};
String [] nomi = {”Mauro”, ”Gianni”};
...
Dinamicamente si crea l’array e si inizializzano i suoi elementi. Gli elementi
specificati possono essere espressioni generiche, e non soltanto espressioni
costanti.
... Il codice riportato a fianco,
int vett []; è giusto o sbagliato?
for (int i=0; i<vett.length; i++) {
vett[i] = i;
}
...
53
Dispense su JAVA
54. Copia di Array
Per copiare tutto o parte di un array si può utilizzare il metodo
arrayCopy(sorg, indexSrc, dest, indexDst, length ) di System.
array da cui copiare num. di elem. da copiare
posizione da dove leggere posizione dove copiare
array su cui copiare
...
char sorg[] = {'d','e','c','a',
'f','f','e','i', indexSrc = 2
'n','a','t','o' ); sorg
d e c a f f e i n a t o
char dest[] = new char[5];
System.arraycopy( sorg, 2, dest, 0, 5 );
System.out.println(new String(dest) length = 5
+ " "
+ new String(sorg) ); indexDst = 0
...
c a f f e
54
Dispense su JAVA
dest
55. Array Multidimensionali (1)
11 12 13
21 22 23
31 32 33
Le seguenti istruzioni creano array di array:
...
int pot [] [] = new int [3] [4];
int param [] [] = { {11, 12, 13}, {21, 22, 23}, {31, 32, 33} };
...
Si possono omettere alcune dimensioni (nelle ultime posiz.).
...
double temp [] [] [] = new double [5] [3] [];
...
Non è lecito scrivere:
...
double temp [] [] [] = new double [5] [] [3];
...
55
Dispense su JAVA
56. Array Multidimensionali (2)
1 2
3 4 5
Si possono definire array non rettangolari: 6 7 8 9
...
int [] [] twodim = { {1,2}, {3, 4, 5}, {6, 7, 8, 9} };
...
Il seguente codice definisce un array triangolare:
...
long triangle [] [] = new long [10] [] ; // array di 10 elementi
for (int i=0; i < triangle.length; i++) { // per ogni elemento
triangle[i] = new long [i+1]; // alloca un array
for (int j=0; j< i+1; j++)
triangle[i] [j] = i+j;
}
...
56
Dispense su JAVA
57. Espressioni
La maggior parte dell’elaborazione in Java consiste nel valutare espressioni.
Ogni espressione ha un tipo associato. Il valore dell’espressione è sempre
conforme al suo tipo.
Durante la valutazione di un’espressione è possibile che vi siano delle
conversioni (cast) implicite di alcuni tipi, ad esempio:
byte = byte + byte; int = short + int; double = int + double;
Java converte automaticamente alcuni tipi in altri che implicitamente
contengono anche quei valori:
short in int
int in double
non converte double in int o int in boolean.
57
Dispense su JAVA
58. Valutazione delle Espressioni (1)
A parità di priorità degli operatori, gli operandi delle espressioni vengono
valutati da sinistra verso destra.
int i = 1;
int j = (i=2) * i; // j vale 4
“ x + y / z ” equivale a “ x + (y/z)”, perché l’operatore “/” ha una
priorità maggiore dell’operatore “+”.
A volte è necessario ricordare risultati parziali:
int t = 3; 3
t += (t=2); // equivale a t = t + (t=2), alla fine t=5
Si consiglia sempre di rendere ogni espressione quanto più leggibile possibile
(per chiarezza e per evitare errori).
58
Dispense su JAVA
59. Valutazione delle Espressioni (2)
Alcune operazioni apparentemente simili possono fornire risultati diversi, il
programma:
class prova {
public static void main(String args[]) {
double d = 8e+307;
System.out.println(4.0 * d * 0.5);
System.out.println(2.0 * d);
}
}
i risultati visualizzati sono:
Infinity // perché la prima operazione provoca overflow
1.6e+308
59
Dispense su JAVA
60. Operatori
Gli operatori eseguono una funzione su uno, due o tre operandi, e
restituiscono un risultato.
Operatori unari agiscono su un solo operando
count++; // incrementa la variabile count di uno
Operatori binari agiscono su due elementi
a + b; // somma di due variabili
a = b; // assegna (non confronta) il valore di b alla variabile a
Operatore ternario (uno solo in Java) agisce su tre elementi
expr ? op1 : op2
se expr è valutata true, restituisce op1, altrimenti restituisce op2
60
Dispense su JAVA
61. Operatori Aritmetici Binari
operatore + op1 + op2
operatore - op1 - op2
operatore * op1 * op2
operatore / op1 / op2
operatore % op1 % op2 // resto della divisione intera
L’operatore + consente anche la concatenazione di stringhe
int count = 10;
String risultato = “Ci sono ” + count + “ elementi.”
la variabile intera count
viene convertita in stringa e
quindi viene concatenata
61
Dispense su JAVA
62. Operatori Aritmetici Unari
notazione notazione
postfissa prefissa
operatore ++ x++ oppure ++x incrementa la variabile di 1
operatore -- x-- oppure --x decrementa la variabile di 1
+ operatore unario +x promuove x a int se byte, short o char
- operatore unario -x negazione aritmetica di x
62
Dispense su JAVA
63. Esempio di Uso degli Operatori ++ e --
... ...
public void push(int c) { public void push(int c) {
if (!full()) { if (!full()) {
top = top + 1; v[++top] = c;
v[top] = c; } else
} else System.out.println(
System.out.println( ”Err: stack pieno”);
”Err: stack pieno”); }
}
public int pop() { public int pop() {
if (!empty()) { if (!empty())
int val = v[top]; return v[top--];
top = top - 1; else
return val; System.out.println(
} else ”Err: stack vuoto”);
System.out.println( }
”Err: stack vuoto”); ...
}
...
sono equivalenti
63
Dispense su JAVA
64. Operatori Relazionali
Confrontano i due operandi determinando la relazione che intercorre tra di
essi, ad es. loperatore “!=” restituisce true se i due operandi non sono uguali
Restituisce true se
> op1 > op2 op1 è maggiore di op2
>= op1 >= op2 op1 è maggiore uguale a op2
< op1 < op2 op1 è minore di op2
<= op1 <= op2 op1 è minore uguale a op2
== op1 == op2 op1 è uguale a op2
!= op1 != op2 op1 è diverso da op2
Normalmente si usano insieme agli operatori logici per costruire espressioni
decisionali complesse.
64
Dispense su JAVA
65. Operatori Logici
Eseguono operazioni logiche tra gli operandi.
Restituisce true se:
&& op1 && op2 operatore AND: op1 e op2 sono entrambi true, op2
viene valutato solo se op1 è true.
|| op1 || op2 operatore OR: almeno un operando è true, op2 è
valutato solo se op1 è false
! ! op1 operatore NOT: op1 è false
& op1 & op2 operatore AND: op1 e op2 sono entrambi true, op2
viene comunque valutato
| op1 | op2 operatore OR: almeno uno tra op1 e op2 è true,
op2 viene comunque valutato
65
Dispense su JAVA
66. Operatori sui Bit
>> op1 >> op2 shift a destra dei bit di op1 di op2 posizioni, estensione del
bit di segno ai bit più significativi (divisione per due)
<< op1 << op2 shift a sinistra dei bit di op1 di op2 posizioni, estensione del
bit di segno ai bit più significativi (moltiplicazione per 2)
>>> op1 >>> op2 shift a destra dei bit di op1 di op2 posizioni, riempie i bit più
significativi di zero.
& op1 & op2 and bit a bit
| op1 | op2 or inclusivo bit a bit
^ op1 ^ op2 (xor) or esclusivo bit a bit
~ ~op1 negazione di ogni singolo bit
66
Dispense su JAVA
68. Precedenze tra Operatori
Ordine di priorità decrescente:
1 Operatori unari
+, -, ++, --
2 Aritmetici binari
*, /, %, +, -, >>, <<
3 Relazionali
<, >, >=, <=, ==, !=
4 Logici e bit
&&, ||, &, |, ^
5 Ternario
A > B ? X : Y
6 Assegnamento
=, +=, -=, *=, ...
68
Dispense su JAVA
69. Operatore Cast
Il cast è utilizzato per convertire un valore da un tipo ad un altro (a patto che ci
sia compatibilità tra i due tipi di dati).
L’operatore di cast si applica a ogni tipo di dato, tipi primitivi (int, char,…) e
oggetti (istanze di classi).
Il cast viene effettuato con la seguente sintassi:
(tipo) variabile
variabile = (tipo) variabile;
...
int x = 3;
double d = 4.2, dd;
dd = (double) x; // converte il valore di x in double, // dd=3.0
x = (int) d; // questa trasformazione elimina la parte decimale
...
69
Dispense su JAVA
70. Operatore instanceof
L'operatore relazionale “instanceof” controlla che l’oggetto a sinistra
dell’operatore appartenga alla classe specificata, restituisce il valore:
true se l’istanza appartiene alla classe
false se l’istanza non appartiene alla classe o se il reference all’oggetto è null.
L'operatore “instanceof” non è applicabile ai tipi primitivi (int, char, …), ma
soltanto a oggetti (istanze di classi).
...
class C {
...
}
...
if ( x instanceof C) ) {
...
}
...
70
Dispense su JAVA
73. I Costrutti di Controllo
Java ha i seguenti costrutti di controllo per il controllo di flusso del
programma:
istruzioni condizionali
if-else
selezione multipla
switch
cicli determinati
for
cicli indeterminati
while
do-while
istruzioni di controllo del flusso di controllo
break label
continue return
73
Dispense su JAVA
74. Istruzione if-else
Sintassi
if (espr) Note
istruzione // istruzione può essere una il tipo boolean non viene
[else // singola istruzione o un convertito in altri tipi
istruzione] // blocco delimitato da { } 0 e null non equivalgono
a false
i valori non-zero o non-
null non equivalgono a
true.
Esempio
...
int count, n;
count = getCount();
if (count < 0) // espressione di tipo boolean
System.out.println(”errore”);
else {
System.out.println(”Ci sono ” + count + ” elementi.”);
n = count;
}
...
74
Dispense su JAVA
75. Istruzione switch
L’istruzione switch è utile nei casi in cui è necessario realizzare selezioni
multiple.
Sintassi Esempio
switch (expr1) { switch (mese) { Note
case expr2: case 4:
case 6: Nelle espressioni dei
istruzioni; case 9: case si possono usare:
break; case 11: numDays = 30;
break; byte
case expr3:
istruzioni; case 2: numDays = 28; char
break; short
break; default: numDays = 31;
default: } int
istruzioni; long
break;
}
75
Dispense su JAVA
76. Istruzione for
L’istruzione for è utile nei casi in cui bisogna realizzare cicli con un
determinato numero di iterazioni.
Sintassi Esempio
for (init_expr; test_expr; incr_expr) { for (int i = 0; i < 10; i++) {
istruzioni; System.out.println(”i= ” + i);
} }
Si possono anche usare espressioni multiple nelle espressioni di inizializzazione e incremento:
int i;
String s;
for ( i = 0, s = ”testo”; // inizializzazione variabili
(i < 10) && (s.length() >= 1 ); // test di continuazione
i++, s = s.substring(1)) { // incremento variabili
System.out.println(s); // corpo del ciclo
}
76
Dispense su JAVA
77. Istruzioni while
L’istruzione while è utilizzata nei casi in cui bisogna realizzare dei cicli con un
numero indeterminato a priori di iterazioni.
Se l’espressione del while viene valutata falsa alla prima iterazione il ciclo
viene saltato completamente.
Sintassi Esempio
while (test_expr) { int i = 10;
while (i-- > 0) {
istruzioni; boolean b = getFlag();
if (b) {
} ...
}
}
77
Dispense su JAVA
78. Istruzione do-while
L’istruzione do-while è utilizzata nei casi in cui bisogna realizzare dei cicli con
un numero indeterminato a priori di iterazioni.
L’istruzione do-while va preferita all’istruzione while quando deve essere
eseguita almeno una iterazione del ciclo.
Sintassi Esempio
do { int i = 10;
istruzioni; do {
boolean b = getFlag();
} while (test_expr); if (b) {
...
} while (i-- > 0) {
78
Dispense su JAVA
79. Istruzioni di Continuazione
o Uscita dal Flusso di Controllo
break [label];
provoca l’uscita dal ciclo in cui è inserita
continue [label];
provoca l’esecuzione della prossima iterazione del ciclo: viene eseguita la
incr_expr e quindi la test_expr del ciclo - for (init_expr; test_expr; incr_expr);
return expr;
esce dal metodo restituendo il valore di expr
label:statement;
etichetta uno statement di tipo for, while o do
79
Dispense su JAVA
80. Esempi di label, break e continue
...
esterno:
while (!done) {
if (condizione)
continue; // va al punto 3
if (condizione)
break; // va al punto 4
for (int i = 0; i < 10; i++) {
if (condizione)
continue; // va al punto 1
if (condizione)
continue esterno; // va al punto 3
if (condizione)
break; // va al punto 2
if (condizione)
break esterno; // va al punto 4
...
} // punto 1. Ultima istruzione del ciclo, ricomincia il ciclo for
// punto 2. Fuori dal ciclo for
...
} // punto 3. Ultima istruzione del ciclo, ricomincia il ciclo while
// punto 4. Fuori dal ciclo while
...
80
Dispense su JAVA