Introduzione a Java
Concetti base
Eclipse, ereditarietà e interfacce
Il problema del progetto
•  I linguaggi classici (C, Pascal, …)
❒ 
❒ 
perfetti per problemi “piccoli”,
facilmente scomponibili in funzioni di
base (es: registratore di cassa, ecc…)
non offrono strumenti mentali adatti ad
affrontare la progettazione di sistemi
software complessi (es: gestionali di
magazzini, ospedali, ecc…).
•  L’uomo non è portato a pensare il
mondo in termini di funzioni… semmai
di oggetti che svolgono funzioni.
Cos’è Java?
•  Linguaggio di programmazione:
❒ 
❒ 
❒ 
❒ 
di alto livello
orientato agli oggetti
progettato per essere il più possibile
indipendente dal SO
… e per semplificare l’attività di
progetto.
Architettura run-time delle
applicazioni java
•  Un’ applicazione Java è strutturata
come un insieme di componenti.
❒ 
❒ 
Alcuni sono statici (vengono caricati
prima dell’inizio del programma ed
Classi
esistono per tutta la durata dello
stesso)
Altri sono dinamici (creati durante
Oggetti
l’esecuzione, al momento del bisogno)
•  Poichè un’ applicazione deve avere
un punto di partenza prestabilito,
uno dei componeneti statici
contiene il main
main
Inversione del punto di vista
•  Questo appoccio porta a invertire il punto di vista:
❒ 
❒ 
l’enfasi non è più sull’operazione svolta (da qualcuno)
ma sull’entità che la svolge
•  In C l’enfasi è sull’OPERAZIONE, il “chi” la svolge è un
dettaglio. (VISIONE PROCEDURALE)
printf(“Hello!”);!
•  In Java (APPROCCIO A OGGETTI) il punto di vista si
inverte: l’enfasi si sposta su CHI offre il servizio.
•  Per esprimere questo cambiamento si usa la notazione
puntata: component.operation(param); !
System.out.println(“Hello!”);!
•  System.out è il componente, println è
l’operazione (metodo)
il main dal C al Java
file myprogram.c
int main(int argc, char* argv[]){ …}!
per convenzione ogni classe deve
!
file MyProgram.java
esser definita dentro un file con
lo stesso nome
public class MyProgram{!
public static void main(String[] args){!
…!
classi devono avere
}! Le
in Java il main deve essere
l’iniziale maiuscola
sempre scritto dentro una
}!
classe “public”
Compilazione: dal mondo C…
myprogram.c
Programma
sorgente C
(testo)
Librerie
stdio.h
string.h
…
Compilatore C e linker alle librerie
-$ gcc myprogram.c –o program.exe
program.exe è:
program.exe
•  scritto in linguaggio macchina
(illeggibile dall’uomo)
•  eseguibile dal SO su cui l’abbiamo
compilato: -$ ./program.exe arg1 arg2…
S. O.
Hardware
Compilazione: … al nuovo mondo: Java
MyProgram.java
Programma sorgente
Java (testo)
Java Compiler
-$ javac MyProgram.java
!
Java Virtual Machine (JVM)
SO
SO
SO
HW
HW
HW
consegnamo il .class
MyProgram.class è:
•  scritto in bytecode (illeggibile dall’uomo) all’esame? …NOOO!
•  eseguibile dall’infrastruttura Java, indipendentemente dal SO!
!-$ java MyProgram arg1 arg2 …!
Esempio 1 – Hello Pinco Pallino!
•  Creare un’applicazione java che prenda in
ingresso due parametri:
❒ 
<nome cognome> di chi esegue il programma
•  Stampi a video: Hello <nome cognome> !!!
Esempio 1 – Soluzione dal C al Java
file myprogram.c
include <stdio.h>!
int main(int argc, char* argv[]){!
printf(“Hello %s!!!“, argv[1]);!
}!
!
file MyProgram.java
public class MyProgram{!
public static void main(String[] args){!
System.out.println(“Hello ”+args[0]+”!!!”);!
}!
0 è il primo parametro, non il
}!
nome del programma, come in C
Semplifichiamoci la vita
…e usiamo Eclipse! (www.eclipse.org)
•  Creare un nuovo progetto:
❒ 
❒ 
❒ 
tasto dx su Package Explore
New -> Java Project
Inserire il nome (es: MyProject) e Finish com’è fatta
•  Creare una nuova classe:
❒ 
❒ 
❒ 
tasto dx sul nome del progetto
New -> Class
Inserire il nome (es: MyProgram) e Finish
la cartella
del progetto
che Eclipse
ci ha creato?
•  Eclipse crea già la nostra prima classe
public class MyProgram{ … }!
Compilazione e esecuzione con
cosa succede nella
Eclipse
•  compiliamo: Project -> Build All
❒ 
cartella del progetto?
cosa leggo aprendo
il .class?!
Eclipse fa per noi: -$ javac MyProgram.java!
•  eseguiamo:
❒ 
senza parametri:
•  tasto dx sul .java che contiene il main -> Run as -> Java Application
❒ 
…ma noi dobbiamo eseguire passando dei parametri:
•  Run -> Run Configurations… -> doppio click su Java Application
•  indichiamo il nome della classe che contiene il main
•  tab Arguments -> scrivo i miei parametri separati da spazi in
Program Arguments
❒ 
Eclipse fa: !
-$ java MyProgram.class “Daniela Loreti” !
I tipi primitivi in Java (1/2)
•  char
•  boolean
❒ 
❒ 
(2 byte)
(1bit)
UNICODE
true/false
boolean è un tipo autonomo. Non si convertono boolean in
interi, neanche con un cast.
le espressioni relazionali e logiche (es: if (x>2) …) danno
come risultato un boolean, (non un int come in c)
Interi:
•  byte
•  short
•  int
•  long
(1byte)
(2byte)
(4byte)
(8byte)
-128…+127
-32768…+32768
-2x109…+2x109
-9x1018…+9x1018
I tipi primitivi in Java (2/2)
Reali:
•  float
(4byte)
-1045…+1045(6-7 cifre sign.)
•  double
(8byte) -10328…+10328(14-15 cifre sign.)
Esempio di guai:
•  float f = Math.sin(Math.PI/3);!
Errore di compilazione: “Possible loss of precision, found
float, required double” oppure “Type mismatch: cannot
convert from double to float”
•  float f = (float) Math.sin(Math.PI/3);!
CAST ESPLICITO. Compilazione OK! Il progettista si
assume esplicitamente la responsabilità della perdita di
precisione.
Esempio 2 – Il contatore
Creare un’applicazione java che simuli un
conta-persone.
•  Quando occorre (es: fine giornata) deve poter essere
resettato.
•  Chiunque lo richieda deve poter sapere quante persone
sono passate.
Comportamento osservabile: è un componente
caratterizzato da:
❒  un valore (intero variabile nel tempo)
❒  e tre operazioni: reset() ; inc() ; getStato()
Vorrei creare un componente riutilizzabile da diversi
main
Il contatore in C
Come faccio in C?
file mycounter.c
stato inaccessibile dall’esterno del file. Così
nessuno potrà mai usare male il mio contatore
nel suo main!
static int stato; !
void reset(void){stato=0};!
void inc(void){stato++;};!
void getStato(void){return stato};!
!
esempio di file mymain.c
file mycounter.h
void reset(void);!
void inc(void);!
void getStato(void);!
!
#include <stdio.h>!
#include “mycounter.h”!
int main(int argc, char* argv[]){!
reset(); inc(); int v = getStato();!
printf(“il contatore attualmente vale %d”,v); !
}!
!
Il contatore in Java
Come faccio in Java?
stato inaccessibile
dall’esterno della classe
public class Contatore{!
file Contatore.java
private int stato = 0;!
attributo
public void reset(){stato=0;}!
public void inc(){stato++;}!
metodi
public int getStato(){return stato;} !
}!
!
public class MyProgram{!
esempio di file MyProgram.java
public static void main(String[] args){!
Contatore c = new Contatore();! costruttore di default
c.reset(); c.inc(); int val = c.getStato();!
System.out.println(“il contatore vale: ”+val);!
}!
è molto più semplice
}!
stampare un valore
E se volessi usare
contemporaneamente
due contatori?
In C mi servirebbero due variabili stato => Mi servirebbe
poter importare 2 volte nel main il file mycounter.c.
int stato; !
void reset(void){stato=0};!
void inc(void){stato++;};!
void getStato(void){return stato};!
!
ma non lo posso fare …qualcosa mi suggerisce che ho
sbagliato tutto!
forse …Avrei dovuto usare typedef!
E se volessi usare
contemporaneamente
due contatori?
In Java:
esempio di file MyProgram.java
public class MyProgram{!
public static void main(String[] args){! Ah! lo posso
fare due
Contatore c1 = new Contatore();!
volte?!
Contatore c2 = new Contatore();!
c1.reset(); c1.inc(); int val1 = c1.getStato();!
c2.reset(); c2.inc(); int val2 = c2.getStato();!
System.out.println(“il contatore 1 vale: ”+val1);!
System.out.println(“il contatore 2 vale: ”+val2);!
}!
Il Contatore non è solo un insieme di funzioni e variabili.
}!
E’ un TIPO DI DATO!
allora lo posso fare anche in C
(1/2)
file mycounter.c
file mycounter.h
#include “mycounter.h”!
typedef int
void reset(contatore* pc){*pc=0};!
contatore; !
void inc(contatore* pc){(*pc)++;};!
…!
void getStato(contatore c){return c};! !
!
esempio di file mymain.c
#include <stdio.h>!
#include “mycounter.h”!
int main(int argc, char* argv[]){!
int v1, v2; contatore c1, c2;!
reset(&c1); reset(&c2); inc(&c1); v1=getStato(c1);!
printf(“il contatore 1 attualmente vale %d”, v1); …!
}!
!
allora lo posso fare anche in C
(2/2)
Definire un tipo di dato in C tramite typedef è possibile,
ma:
•  non c’è unitarietà tra parte-dati (espressa con typedef
nel mycounter.h) e parte-operazioni (scritte
successivamente e altrove, ad es. nel mycounter.c)
•  non c’è protezione dall’uso improprio, perchè tutti vedono
typedef e dunque tutti possono aggirarla
•  le signature delle operazioni fanno trasparire dettagli (I
puntatori…) che non dovrebbero entrare in gioco a questo
livello!
=> il livello di espressività di C non è adeguato!
Oggetti Java come istanze di
Classi
Gli oggetti java sono componenti sw DINAMICI,
creati a immagine e somiglianza di una classe
•  si possono creare tutte le istanze che servono
•  la creazione avviene run-time al momento del
bisogno
OGGETTI Contatore,
ISTANZE della
classe Contatore!
classe String
•  In java le stringhe non sono più array di
caratteri. Sono OGGETTI, istanze della
CLASSE String!
•  Java lo sottolinea impedendo di applicare gli
operatori classici degli array, come []: per
selezionare il carattere i-esimo si usa charAt!
String s = “pippo”;!
char c = s.charAt(i); //c=“i”!
!
•  ci sono tantissime operazioni invocabili sulle
stringhe => usare il suggest di Eclipse:
❒ 
nell’esempio precedente, dopo aver digitato “s.”
provare la combinazione ctrl+Space)
Contatore con 2 costruttori
public class Contatore{!
file Contatore.java
private int stato;!
i costruttori
public Contatore(){stato = 0;};!
sono metodi
public Contatore(int val){stato = val};! particolari che
public void reset(){stato=0;}!
dicono come
devono essere
public void inc(){stato++;}!
inizializzati gli
public int getStato(){return stato;} !
oggetti
}!
!
public class MyProgram{!
esempio di file MyProgram.java
public static void main(String[] args){!
Contatore c1 = new Contatore();!
Contatore c2 = new Contatore(10);…!
}!
Chiama il secondo costruttore.
c2 è inizializzato a 10
}!
la keyword this
Oppure:
public class Contatore{!
file Contatore.java
private int stato;!
public Contatore(){};!
public Contatore (int stato){this.stato = stato};!
public void reset(){stato=0;}!
public void inc(){stato++;}!
public int getStato(){return stato;} ! denota l’oggetto
corrente. di
}!
norma
!
sottintesa, ma
può essere
specificata se
occorre.
Riferimenti
•  in C si possono definire, per ciascun tipo:
❒ 
❒ 
sia variabili (es: int x;)
sia puntatore (es: int* px;)
•  in Java il linguaggio impone due scelte:
❒ 
❒ 
varabili per tipi primitivi
(es: int x;)
passaggio di parametri per VALORE
riferimenti per gli oggetti
(es: Contatore c;).
passaggio per RIFERIMENTO
Riferimenti: cosa ci si può fare
•  Definirli senza inizializzarli
Contatore c;
•  Assegnare loro la costante null
c=null;!
questo riferimento non punta a nulla
•  Usarli per creare nuovi oggetti
!
!
!
!
!c = new Contatore();!
c
•  Assegnarli uno all’altro:
!Contatore c2 = c;!
c2
oggetto
c2 adesso referenzia lo stesso oggetto di c
Contatore
•  Confrontarli:
c == c2 !
è vera se puntano allo stesso oggetto,
NON se hanno lo stesso valore!
gli array di java
Gli array in java sono oggetti, istanze di una
classe speciale denotata da []
Quindi come per ogni oggetto:
•  prima di definisce un riferimento
int[] v;!
Contatore[] w; !
•  poi si crea dinamicamente l’istanza
v = new int[3];!
w = new Contatore[6]; !
gli array di java
nel primo caso ogni elemento dell’array è una
variabile normale, tipo primitivo:
v = new int[3]; v[0]=4; v[2]=34;!
!
v
34
4
nel secondo caso ogni elemento dell’array è un
riferimento a oggetto:
w = new Contatore[6];!
w[0] = new Contatore(10); !
!
w
!
10
Ereditarietà
Spesso capita di aver bisogno di un componente simile a
uno già esistente, ma non identico.
es: voglio un contatore che sappia anche decrementare!
public class ContatoreDec extends Contatore {!
public void dec(){stato--;}!
file ContatoreDec.java
}!
!
public class Contatore{!
file Contatore.java
protected int stato;!
con private la variabile stato non
public Contatore(){}; …!
sarebbe visibile in ContatoreDec
}!
MyProgram.java
c2=new ContatoreDec(30);!
c2.inc(); !
Posso invocare tutti I metodi public di
c2.dec();!
Contatore e ContatoreDec!
!
Ereditarietà – tutto è Object!
In Java tutte le classi ereditano implicitamente da una classe
di sistema: Object. Da essa ereditano alcuni metodi di
default:
c1
•  boolean equals(Object o);!
c2
oggetto
c1.equals(c2); equivalente a (c1==c2).
Contatore
restituisce true se sono = i riferimenti.
•  String toString();!
implicitam. chiamato
Contatore.toString()
System.out.println(“c=”+c);
c=Contatore@38da9246!
System.out.println(“c=”+c.getStato());
c=24!
Integer.toString()
Ereditarietà – tutto è Object!
ma questi metodi di Object possono essere ridefiniti.
basta aggiungerli tra i metodi del Contatore:
Lo controllo
public class Contatore{ …!
perchè
public boolean equals(Object obj){! Object obj
potrebbe esser
if (obj instanceof Contatore) !
qualunque cosa
return ((Contatore)obj).getStato() == stato;!
else return false;!
}!
public String toString(){!
return “Questo contatore vale ”+this.stato;!
}!
System.out.println(“c=”+c); !
ora stampa: c=Questo contatore vale 24
}!
Classi astratte
•  Moltissime entità che usiamo per descrivere il mondo
non sono reali, ma sono utili per esprimersi.
•  es: Gli Animali
❒  parlare di “animali” ci è molto utile, ma a ben
pensarci non esiste il generico animale!
❒  nella realtà esistono solo animali specifici: “gatto”,
“cane”, “serpente” …
•  per questo esistono le classi astratte! Sono come le
classi normali, ma da qualche parte esprimiamo la
convenzione di non crearne mai istanze
❒ 
❒ 
public abstract class Animale{ … }!
ci posso metter dentro metodi e attributi comuni agli animali
Classi astratte …esempio concreto
public abstract class Animale{!
l’attributo mioNome
private String mioNome;!
ce l’hanno tutti!
Cambia il suo valore!
protected String verso;!
protected Animale(String s){mioNome=s;}!
public abstract String nomeComune();!
metodi
public abstract String siMuove();!
astratti
public abstract String doveVive();!
public void mostra(){!
System.out.println(mioNome+”: è un “
+nomeComune()+”, si muove ”+siMuove()+” e vive
” +doveVive());!
mostra() usa i metodi astratti
anche se nessuno ha ancora definito
}!
cosa fanno. POLIMORFISMO
}!
Ereditarità e classi astratte
•  Chiunque estenda una classe (normale
o astratta) vedrà i suoi metodi e
attributi protected e public.
•  Posso ereditare a cascata da classi
(normali o astratte) -> le
classificazioni sono spesso ad albero.
•  Java NON supporta l’ereditarietà
multipla -> posso estendere una sola
classe
Altro esempio
•  Voglio modellare le classi Studente e
Lavoratore.
•  Presumibilmente le farò estendere una classe
Persona!
•  ma come modello uno
StudenteLavoratore?
Interfacce
•  Certe volte mi fa proprio comodo definire solo le operazioni
che una certa classe di oggetti può compiere.
•  spesso occorre ereditarietà multipla …ma senza mescolare le
implementazioni!!!
public interface IStudente{public int getMatricola();}!
public interface ILavoratore{!
solo i nomi delle operazioni…
public int getStipendio();!
non mi interessa (e non
posso) dire qui cosa fanno!
}!
public class Studente implements IStudente{…}!
public class Lavoratore implements ILavoratore{…}!
public class StudenteLavoratore !
!
!
!implements IStudente, ILavoratore{…}!
!Devo definire le operazioni di tutte le
!interfacce che implemento!
Esercizio 3 - Corsa Mista
Implementare un’applicazione java che simuli una gara
di corsa tra concorrenti “molto diversi”
Tutti i concorrenti hanno un nome proprio, una
matricola (numero intero) e una velocità (float,
supponiamola costante).
Per tutti i concorrenti deve esser possibile:
•  stampare una breve descrizione
•  calcolare il tempo di percorrenza data una certa
distanza
Corsa Mista
Possono gareggiare:
•  concorrenti inquinanti (auto e moto): che usano un
certo tipo di carburante, hanno una marca e sono
dotati di una certa autonomia in km, esaurita la
quale, non potendo rifornirsi, devono ritirarsi.
❒  Le auto hanno anche un numero di passeggeri
(da 1 a 5)
•  concorrenti ecologici (bicicletta e cavallo)
Corsa Mista
Le biciclette e tutti i veicoli inquinanti sono a conducente
umano e come tali devono riposarsi per R ore ogni G ore di
guida.
R = random tra 6 e 8
G = random tra 10 e 12
calcolaOreDiSonno()
calcolaOreDiGuida()
•  Le auto con più di un passeggero tuttavia non hanno
bisogno di interrompere la gara.
•  I cavalli non dormono mai!
Si simuli una corsa per T Km con numero di partecipanti a
piacere (anche più concorrenti dello stesso tipo)
•  si stampi a video la descrizione di ciascuno in ordine di
arrivo!
Esercizio 3 - Suggerimenti
•  non esiste il generico Concorrente,
ConcorrenteInquinate o ConcorrenteEcologico, come
non esisteva il generico Animale
•  auto, moto, cavalli e biciclette possono essere divisi
secondo due classificazioni:
❒ 
❒ 
Inquinanti (auto, moto) – Ecologici (bici, cavallo)
ConducenteUmano (auto, moto, bici) – ConducenteAltro (cavallo)
•  Con una semplice gerarchia di classi non posso mappare
questa realtà perchè non esiste l’ereditarietà multipla.
•  Posso definire un insieme di operazioni che solo auto,
moto e bici devono fare? -> se si, posso definire
l’interfaccia IConducenteUmano!
Esercizio 3 - Suggerimenti
•  generare un numero random con Java: Math.random()
restituisce un double tra 0 e 1. Quindi se invece voglio
un int tra min e max:
(int) min + Math.random()*(max-min+1)
•  cercate di replicare meno codice possibile. Es: se due
classi devono compiere la stessa operazione, possiamo
scrivere il metodo corrispondente una volta sola in una
superclasse concreta o astratta che sia.