![]() |
Importante: Il sito di Fondamenti di Informatica C e' stato spostato sul nuovo portale wiki di Agent Group.
Pertanto, questo sito non verrˆ pi aggiornato.. |
![]() |
Pagina delle FAQ sulla tesina: alla seguente pagina sono raccolte le risposte alle domande e dubbi posti dagli studenti al docente ed ai tutor. |
![]() |
E' disponibile il testo (file tesina07-08.pdf) della tesina
da svolgere per l'anno accademico 07-08. Questo testo verra' discusso e ulteriormente spiegato durante
l'esercitazione in laboratorio di Giovedi 10 Maggio 2008.
Alcune istruzioni per installare JMF (Java Media Framework) su Mac OS X: JMF on OS X |
In questa pagina vengono riassunte tutte le esrcitazioni fatte in laboratorio. Viene messo a disposizione degli studenti del corso il materiale didattico usato durante le esercitazioni (lucidi, codici sorgenti, testi degli esercizi).
In caso di problemi contattare Raffaele Quitadamo: raffaele.quitadamo@unimore.it
(ricevimento solo su appuntamento, da fissare via e-mail)
Il materiale delle esercitazioni verrà aggiunto progressivamente durante il corso.
ESERCITAZIONE 1 | ||||||||||||
Data dell'esercitazione | Riassunto degli argomenti trattati | |||||||||||
10/04/2008, laboratorio base |
Programmazione ad oggetti: motivazioni e vantaggi. Astrazione di dati e implementazione
mediante linguaggi non orientati agli oggetti; discussione su vantaggi e svantaggi. Implementazione di un dato astratto e di un tipo di dato astratto per la gestione di un conto corrente in C. Utilizzo dei metodi per incapsulare operazioni, controlli sui parametri e sui dati di ingresso di ogni operazione. Cenni su altre implementazioni OOP possibili in C (si veda la sezione Materiale aggiuntivo). |
|||||||||||
Download | ||||||||||||
|
ESERCITAZIONE 2 | |||||||
Data dell'esercitazione | Riassunto degli argomenti trattati | ||||||
17/04/2008, laboratorio base |
Introduzione agli ambienti di sviluppo IBM Eclipse e NetBeans: progetti, file sorgenti, compilazione ed esecuzione.
Cenni sul sistema di controllo delle versioni Subversion ed installazione del plugin subeclipse
per Eclipse. Si vedano le pagine:
Esempi di errori di compilazione di esecuzione, con particolare riferimento a NullPointerException e ArrayIndexOutOfBounds . |
||||||
Download | |||||||
|
ESERCITAZIONE 3 | |||||||
Data dell'esercitazione | Riassunto degli argomenti trattati | ||||||
24/04/2008, laboratorio base |
Ereditarieta': costruzione di gerarchie di classi, classi
astratte, specificatori di accesso e classi |
||||||
Download | |||||||
|
ESERCITAZIONE 4 | ||||||||||||
Data dell'esercitazione | Riassunto degli argomenti trattati | |||||||||||
08/05/2008, laboratorio base |
Input/Output su file, in modalita' testuale e binaria, con
particolare attenzione agli stream. Utilizzo delle classi BufferedStreamReader e BufferedStreamWriter per l'I/O testuale. Utilizzo delle classi DataOutputStream e DataInputStream per la scrittura/lettura di tipi di dati primitivi da stream; ObjectOutputStream e ObjectInputStream per la scrittura/lettura di interi oggetti da stream; introduzione ai concetti di serializzazione. Introduzione alle eccezioni e ai blocchi try...catch .
Implementazione di un esercizio di serializzazione binaria e testuale di un insieme di classi Famiglia e Persona. Viene fornito come materiale aggiuntivo un esercizio che mostra la lettura di input utente da STDIN, oltre ad un esercizio ulteriore di serializzazione di oggetti e di scrittura/lettura di parametri testuali nella forma chiave=valore. |
|||||||||||
Download | ||||||||||||
|
ESERCITAZIONE 5 | |||||||
Data dell'esercitazione | Riassunto degli argomenti trattati | ||||||
15/05/2008, laboratorio base |
Introduzione alla grafica Java: utilizzo dei pannelli per disegnare, realizzazione di finestre di primo livello (Frame) e gestione degli eventi dei menu'. Utilizzo di archivi Jar e della relativa documentazione Javadoc. Realizzazione di un esercizio che visualizzo il grafico di una opportuna funzione. Controllo dei parametri e utilizzo dell'eccezione IllegalArgumentException . Utilizzo delle classi Adapter e
implementazione di una semplice classe per la chiusura dell'applicazione
e della relativa finestra.
|
||||||
Download | |||||||
|
ESERCITAZIONE 6 | |||||
Data dell'esercitazione | Riassunto degli argomenti trattati | ||||
22/05/2008, laboratorio base |
Componenti Swing di base: pulsanti, caselle di testo, pannelli
con scrolling, ecc. Gestione degli eventi ActionEvent . Realizzazione
di un programma con GUI per la gestione di note di testo semplice.Utilizzo dei layout manager. Viene fornito come materiale aggiuntivo una esercitazione simile ma che prevede la gestione di lettere di testo. |
||||
Download | |||||
|
ESERCITAZIONE 7 | ||||||||||||||||
Data dell'esercitazione | Riassunto degli argomenti trattati | |||||||||||||||
29/05/2008, laboratorio base |
Trattamento di liste ad array: aggiunta e rimozione di
elementi. Come implementare l'interfaccia List e come preparare
gli oggetti che devono essere memorizzati in una lista, con particolare
riferimento alla sovrascrittura del metodo equals(..). Gestione
degli errori attraverso le eccezioni. |
|||||||||||||||
Download | ||||||||||||||||
|
ESERCITAZIONE 8 | |||
Data dell'esercitazione | Riassunto degli argomenti trattati | ||
05/06/2008, laboratorio base |
Lezione ed esercitazione sui thread Java. |
||
Download | |||
|
ESERCITAZIONE 9 | |||
Data dell'esercitazione | Riassunto degli argomenti trattati | ||
12/06/2008, laboratorio base |
Gestione di alberi binari: introduzione e problematiche
nell'utilizzo di tecniche ricorsive. |
||
Download | |||
|
Le tastiere con un layout differente da quello americano non hanno dei tasti con le parentesi graffe. E' possibile ottenere tali parentesi in uno dei seguenti modi (alcuni potrebbero non funzionare a seconda del programma usato):
ALT
e digitare 123 per la parentesi aperta, 125 per quella chiusa
ALT GR
, il tasto posto a destra) e i tasti con le parentesi
quadre per ottenere quelle graffe
ALT GR
, il tasto posto a destra) e il numero 7
per la
parentesi aperta, 8
per quella chiusa.
ALT+SHIFT
e' possibile cambiare il layout fra americano e italiano, e quindi
utilizzare la tastiera come se fosse americana.
Exception in thread "main" java.lang.NoSuchMethodError: main
main
o che non
lo dichiara con il prototipo corretto. Si ricordi che il prototipo del main
e' il seguente:
public static void main(String argv[])
Exception in thread "main" java.lang.NoClassDefFoundError:
classpath
.
Exception in thread "main" java.lang.NullPointerException
null
, e quindi occorre fare una escplicita
istanziazione. Ad esempio:
ContoCorrente cc; // dichiara solo il riferimento => cc vale null
...
cc = new ContoCorrente(..); // ora posso usare cc senza problemi di NullPointerException
new
:
int vettore[];
...
vettore = new int[10];
Exception in thread "main" java.lang.ArrayIndexOutOfBounds
cannot resolve symbol
int laMiaVariabile;
...
laTuaVariabile=10; // variabile non dichiarata prima => errore di battitura,ecc.
duplicated class
.class
) e ricompilare il progetto. Se ancora si verificano dei problemi,
si controlli di non avere alcun sorgente nelle directory in cui vengono inserite le classi compilati.
Utilizzando il JCreator, questo errore potrebbe verificarsi quando una classe viene spostata da un package
all'altro, ossia quando si è compilata una classe come appartenente al package X
, cambiandone
poi la clausola package
e ricompilando da capo. In questo caso si suggerisce di eliminare il
vecchio codice sorgente e, se necessario, creare un nuovo progetto importando i sorgenti con le definizioni
di package corrette.
Le eccezioni rappresentano errori di esecuzione. Il sistema di eccezioni di Java è
molto completo e complesso, per una sua trattazione si rimanda alle lezioni del prof.Cabri.
Tuttavia, anche senza conoscere i dettagli di funzionamento del meccanismo ad eccezioni,
è possibile utilizzarle per scovare gli errori nei programmi e quindi correggerli.
Ecco come si presenta l'output di un programma che genera un'eccezione.
Exception in Thread "main": java.lang.ArrayIndexOutOfBoundsException: 10
at jaas.Untitled1.main(Untitled1.java:18)
Exception in thread "main"
La prima riga riporta la classe che identifica il tipo di eccezione/errore (in questo
caso java.lang.ArrayIndexOutOfBoundsException). E' possibile cercare nella documentazione
Javadoc il significato attribuito alla classe di eccezione, ossia le condizioni in cui
tale errore si verifica.
La seconda riga indica il punto in cui l'eccezione si è verificata, in modo che il programmatore
possa trovare corrispondenza nel codice sorgente. L'indicazione sull'errore è formattata
nel seguente modo:
package.nome_classe.nome_metodo(nome_file:riga)
Per produrre la documentazione Javadoc si puo' utilizzare il comando javadoc
da una finestra
prompt dei comandi o, in alternativa, si puo' impostare l'ambiente JCreator affinchè esegua javadoc
direttamente.
In entrambi i casi è consigliata la configurazione del PATH
in maniera opportuna per
gli strumnti del compilatore Java (si vedano a tal proposito i lucidi
installazione_java.pdf).
Da prompt dei comandi:
javadoc -private *.java
javadoc *.java
. Confermare con il pulsante OK e chiudere la
finestra delle opzioni.
Quelli che seguono sono alcuni semplici risultati di un confronto fatto su versioni differenti delle JVM
prodotte da SUN. Tali risultati non sono da considerarsi definitivi e/o professionali, e sono forniti
al solo scopo di dare un'idea dei tempi di esecuzione delle singole JVM.
Il frammento principale del codice Java utilizzato e' il seguente:
for(int i=0;i<500;i++)
for(int j=0;j<500;j++)
for(int k=0;k<500;k++)
Math.sqrt( (double) i+j+k );
ove si faceva variare l'indice comune ai cicli for
per ottenere un numero complessivo di radici
calcolate differente. I programmi sono stati compilati con il compilatore a corredo della JVM, al fine di
usufruire di tutte le ottimizzazioni possibili. I test sono stati eseguiti su una workstation SUN Ultra Sparc
con sistema operativo SUN Solaris 5.8
Test eseguito | JVM 1.2.2 | JVM 1.4.2 | JVM 1.5.0 beta |
50^3 | 26-28 msec | 117-147 msec | 152-164 msec |
500^3 | 26,533 sec | 27,178 sec | 27,601 sec |
500^3 + apertura di un JFrame | 32,709 sec | 31,059 sec | 33,193 sec |
Fra gli strumenti del JDK è presente javap
che consente di disassemblare una classe compilata
in formato umanamente leggibile. Ecco un esempio di decompilazione:
javap
con l'opzione
-c
, specificando la classe (compilata) da disassemblare:
javap -c Cliente
javap
i programmatori possono analizzare l'output di una compilazione
studiando cosi' il comportamento del compilatore e le eventuali ottimizzazioni possibili.
La creazione di programmi di rete, ossia di programmi capaci di comunicare con
altri programmi per mezzo di connessioni di rete, richiede la conoscenza
di alcuni concetti fondamentali riguardanti i Thread e le Socket.
Tuttavia, ricordando che Java gestisce tutto l'input/output per mezzo di stream,
e' possibile nascondere i dettagli relativi alle connessioni in classi
di piu' alto livello, che possono essere utilizzate nei propri programmi.
Le classi presentate di seguito, appartenenti al package fluca.net
servono appunto a facilitare la creazione di applicazioni di rete client/server
nascondendo la gestione dei thread e delle socket al programmatore, che deve
quindi preoccuparsi solo di gestire opportunamente gli stream dati.
La struttura del package e' mostrata nella seguente figura:
BaseNetClass
funge da capostipite
della gerarchia, fornendo solo alcuni servizi comuni alle classi che implementano
il client e il server (rispettivamente
BaseClient
e BaseServer
).
BaseServer
incapsula un server con il proprio thread di
esecuzione, l'unica informazione necessaria per la creazione di un server e'
il numero di porta sul quale questo dovra' restare in ascolto. Una volta avviato,
il server restera' in ascolto fino al sopraggiungere di una connessione, che sara'
opportunamente servita, per poi tornare ad attendere altre connessioni. E'
possibile arrestare il server mediante il metodo stop()
.
BaseClient
fornisce i servizi base per la gestione di
un client; il suo metodo principale, connectTo(..)
, consente
di stabilire la connessione verso un server in esecuzione.
ConnectionManager
per trattare opportunamente
la connessione. Appena il server riceve una connessione, invoca il metodo
manageConnection(..)
dell'interfaccia ConnectionManager
passando gli stream (ObjectInputStream
e
ObjectOutputStream
) agganciati alla connessione. Similarmente,
appena il client riesce a stabilire una connessione con il server, invoca
lo stesso metodo su una implementazione di ConnectionManager
.
E' quindi sufficiente implementare l'interfaccia di cui sopra per gestire
il protocollo di comunicazione fra client e server. Tipicamente client e
server avranno una implementazione di ConnectionManager
differente, ma in casi molto semplici (come l'esempio qui di seguito proposto)
l'implementazione potrebbe anche essere la stessa.
Il seguente esempio mostra l'utilizzo delle classi sopra descritte
per implementare un semplice programma client/server dove client e server
si scambiano un messaggio:
// creo i connection manager relativi alla connessione
ConnectionManager server = new MyConnectionManager("Messaggio dal server");
ConnectionManager client = new MyConnectionManager("Messaggio dal client");
// creo il server, che esegue su un thread proprio
BaseServer bServer = new BaseServer(3663, server, true);
// creo il client
BaseClient bClient = new BaseClient(client);
// dico al client di collegarsi alla porta del server sull'host locale
bClient.connectTo("localhost",3663);
// a questo punto la gestione delle connessioni e' automatica!
// posso stampare i messaggi che il client e il server si sono scambiati
System.out.println("IL SERVER HA RICEVUTO: "+((MyConnectionManager)client).getMessaggio());
System.out.println("IL CLIENT HA RICEVUTO: "+((MyConnectionManager)server).getMessaggio());
// dico al client di chiudere la connessione
bClient.closeConnection();
MyConnectionManager
ha la seguente implementazione:
public class MyConnectionManager implements ConnectionManager{
private String messaggio;
public MyConnectionManager(String messaggio){
this.messaggio = messaggio;
}
public void manageConnection(SocketAddress remoteAddress,
ObjectInputStream input,
ObjectOutputStream output,
boolean canRead,
boolean canWrite){
try{
// scrivo il messaggio verso l'altro capo della connessione
if( canRead )
output.writeObject(messaggio);
// leggo il messaggio: faccio un ciclo per una read non bloccante
do{
this.messaggio = (String) input.readObject();
}while( this.messaggio == null && canWrite);
}catch(IOException e){
System.err.println("Errore in scrittura/lettura");
e.printStackTrace();
}
catch(ClassNotFoundException e){
System.err.println("Errore in ricerca classe letta");
e.printStackTrace();
}
}
public String getMessaggio(){
return this.messaggio;
}
}
[note.net.BaseServer - main] Devo creare un nuovo thread demone per questo server
[note.net.BaseServer - main] Avvio il thread del server
[note.net.BaseServer - main] thread del server avviato
[note.net.BaseClient - main] Tentativo di connessione a localhost/127.0.0.1:3663
[note.net.BaseClient - main] Gestisco la connessione attraverso il connection manager net.test.MyConnectionManager
[note.net.BaseClient - main] Stream di output pronto
[note.net.BaseClient - main] Stream di input pronto
[note.net.BaseServer - BaseServerThread] Socket server creata, entro nel ciclo di attesa
[note.net.BaseServer - BaseServerThread] Attendo una nuova connessione...
[note.net.BaseServer - BaseServerThread] connessione ricevuta!
[note.net.BaseServer - BaseServerThread] Client:/127.0.0.1:1932
[note.net.BaseServer - BaseServerThread] Gestisco la connessione attraverso il connection manager net.test.MyConnectionManager
[note.net.BaseServer - BaseServerThread] Stream di output pronto
[note.net.BaseServer - BaseServerThread] Stream di input pronto
[note.net.BaseClient - main] Gestione connessione terminata
[note.net.BaseServer - BaseServerThread] Gestione connessione terminata
IL SERVER HA RICEVUTO: Messaggio dal client
IL CLIENT HA RICEVUTO: Messaggio dal server
[note.net.BaseServer - BaseServerThread] Risveglio di eventuali thread sospesi su richiesta di stream
[note.net.BaseServer - BaseServerThread] Attendo una nuova connessione...
ConnectionManager
per il client
e una per il server; utilizzare gli stream forniti per scrivere e leggere
oggetti;BaseServer
legato ad una
porta e fornire il relativo ConnectionManager
;connectTo
;
E' presente anche un sottopackage, fluca.net.secure
che fornisce
una implementazione di server e client con concetti di sicurezza basati su Grant
. Un grant e' un oggetto che descrive alcune proprieta' che occorre avere
per accedere ad una connessione (ad esempio uno username e una password). Il
client invia il grant al server che lo controllo con il proprio, se i dati
contenuti nel grant coincidono la connessione viene concessa, altrimenti rifiutata.
Si veda la documentazione javadoc per maggiori dettagli.
E' possibile scaricare il file jar da importare nei propri progetti qui:
fluca.net.jar.
La documentazione javadoc puo' essere consultata qui.
Infine, sono disponibili anche i file sorgenti.