









Studia grazie alle numerose risorse presenti su Docsity
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
Prepara i tuoi esami
Studia grazie alle numerose risorse presenti su Docsity
Prepara i tuoi esami con i documenti condivisi da studenti come te su Docsity
Trova i documenti specifici per gli esami della tua università
Preparati con lezioni e prove svolte basate sui programmi universitari!
Rispondi a reali domande d’esame e scopri la tua preparazione
Riassumi i tuoi documenti, fagli domande, convertili in quiz e mappe concettuali
Studia con prove svolte, tesine e consigli utili
Togliti ogni dubbio leggendo le risposte alle domande fatte da altri studenti come te
Esplora i documenti più scaricati per gli argomenti di studio più popolari
Ottieni i punti per scaricare
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
Come vengono organizzati i file .class e JAR in Java, inclusa la nomenclatura delle classi, la creazione di file JAR e l'uso di generics per creare liste sicure. Vengono inoltre illustrati i metodi per la creazione di oggetti File e la gestione dei file e delle directory. Infine, vengono forniti dettagli sull'ottenimento della data e dell'ora locali in Java.
Tipologia: Guide, Progetti e Ricerche
1 / 17
Questa pagina non è visibile nell’anteprima
Non perderti parti importanti!










Corso di Progettazione del Software, A.A. 2004/ Docente: Massimo Mecella, tutor: Massimiliano de Leoni
Massimiliano de Leoni
L’intento di questo documento è di descrivere alcune caratteristiche di Java non descritte sul testo. Le funzionalità descritte sono le seguenti:
La classe File.................................................................................................................................... JFileChooser .................................................................................................................................... JOptionPane ..................................................................................................................................... La visualizzazione di tabelle in Java................................................................................................ La classe JTextArea ......................................................................................................................... La classe Timer .............................................................................................................................. La gestione degli eventi del mouse: MouseListener...................................................................... Organizzazione dei file .class di un progetto: i file JAR ............................................................... Ottenimento della date e dell'ora locale ......................................................................................... Note riguardo JDK 1.5 ...................................................................................................................
Questa classe è parte del package java.io. Sebbene la maggior parte delle classi definite da questo package agisce sui flussi, la classe File non lo fa; tratta direttamente con i file e con il sistema di cartelle: non specifica quali informazioni vengono recuperate dai file ma descrive le proprietà del file stesso. Un oggetto File viene visualizzato per ottenere o manipolare le informazioni associate ad un file sul disco, quali i permessi, l’ora, la data e il percorso della directory e per gestire le gerarchie delle sottodirectory. Infatti, una directory viene tratta come File, con un’ulteriore proprietà: un elenco di nomi di file che può essere esaminati con un metodo. Per creare oggetti File possono essere utilizzati i seguenti costruttori:
File(String pathDir) File(String pathDir,String nomeFile) File(File dirObj,String nomeFile)
dove pathDir è il nome di percorso del file, nomeFile è il nome del file e dirObj è un oggetto File che specifica una directory. Per quanto riguarda i separatori nel percorso Java accetta sia lo standard Unix/Internet con la barra (/) sia la convenzione Windows/DOS di barra rovesciata () con l’accortezza di dover utilizzare la sua sequenza di escape (\) in una stringa. Ad esempio per creare un oggetto file che referenzi la radice di un disco si può fare indistintamente nei due seguenti modi
File f1=new File(“/”); File f2=new File(“\”);
A questo punto, ad esempio, per creare un riferimento al file autoexec.bat presente nella radice del disco si può fare:
File f3=new File(f1,”autoexec.bat”); File f3=new File(“/autoexec.bat”); File f3=new File(“/”,”autoexec.bat”);
Corso di Progettazione del Software, A.A. 2004/ Docente: Massimo Mecella, tutor: Massimiliano de Leoni
Le tre operazioni sono identiche; il programmatore può scegliere il costruttore di volta in volta più comodo.
Di seguito alcuni dei metodi più utili messi a disposizione dalla classe: boolean exists() Restituisce true se l’oggetto File si riferisce ad un file che esiste boolean isDirectory() Restituisce true se l’oggetto File si riferisce ad una directory boolean isFile() Restituisce^ true^ se l’oggetto File si riferisce ad un file regolare String getName() Restituisce il nome del file referenziato dall’oggetto File String getAbsolutePath() Restituisce il percorso completo del file ref. dall'oggetto File int length() Restituisce la dimensione del file
boolean renameTo(File f)
Il nome del file specificato dal parametro diventa il nuovo nome dell’oggetto file. Restituisce true in caso di successo. boolean delete() Cancella il file referenziato dall’oggetto File String[] list() File[] listFiles()
Se l’oggetto File si riferisce ad una directory, i due metodi restituiscono la lista dei file e delle directory presenti sottoforma di un array di stringhe o di oggetti File
Un ultima osservazione: le classi che agiscono sui flussi come FileInputStream o FileWriter , ammettono un costruttore che prende in ingresso direttamente un oggetto file. Ad esempio se f è un oggetto File si può scrivere
FileInputStream in = new FileInputStream(f); FileWriter out = new FileWriter(f);
Corso di Progettazione del Software, A.A. 2004/ Docente: Massimo Mecella, tutor: Massimiliano de Leoni
L'intero che viene restituito può assumere tre valori:
JFileChooser.APPROVE_OPTION (^) Se è stato premuto il bottone di conferma JFileChooser.CANCEL_OPTION (^) Se è stato premuto il bottone Cancel JFileChooser.ERROR_OPTION (^) Se si è verificato un errore.
Per conoscere il risultato dell'interrogazione è possibile usare i seguenti metodi:
File getCurrentDirectory() File getSelectedFile()
che restituiscono rispettivamente la directory corrente e il file selezionato come oggetto File.Altri metodi permettono un uso più avanzato:
void setDialogTitle(String titolo) Imposta il titolo della finestra del utilizzando come parametro una stringa^ JFileChooser
void setApproveButtonText(String titolo)
Imposta il testo del bottone di conferma del JFileChooser utilizzando il parametro stringa
void setFileSelectionMode(int modo)
Permette di selezionare solo file, directory o entrambi, utilizzando come parametro uno dei seguenti valori:
JFileChooser.FILES_ONLY (^) Solo i file JFileChooser.DIRECTORY_ONLY Solo le directory JFileChooser.FILES_AND_DIRECTO RIES Entrambi void setMultiSelectionEnabled(boolea n a)
Abilita o disabilita la possibilità di selezionare più di un file alla volta
File[] getSelectedFiles()
Se è possibile selezionare più di un file alla volta, restituisce un vettore contenente i file selezionati dall'utente
Esempio
import java.io.File; import javax.swing.JFileChooser;
public class Application { public static void main(String args[]) { JFileChooser fc=new JFileChooser(); fc.setApproveButtonText("Apri"); int value=fc.showOpenDialog(null); while(value==JFileChooser.APPROVE_OPTION) { File f=x.getSelectedFile(); System.out.println("É stato selezionato il file "+f); value=fc.showOpenDialog(null); } System.exit(0); } }
Corso di Progettazione del Software, A.A. 2004/ Docente: Massimo Mecella, tutor: Massimiliano de Leoni
Message Dialog
Confirm Dialog
Input Dialog
La classe javax.swing.JOptionPane permette di realizzare facilmente finestra modali di input, di allarme o di conferma. Le API di JOptionPane mettono a disposizione tre tipi di pannelli: Confirm, Input e Message Dialog. Il primo viene usato quando si deve chiedere all'utente di effettuare una scelta tra un gruppo di possibilità, il secondo torna utile quando si deve richiedere l'inserimento di una stringa di testo mentre il terzo viene usato per informare l'utente. La classe JOptionPane fornisce un gruppo di metodi statici che permetto di creare facilmente queste finestre ricorrendo ad una sola riga di codice. In questo paragrafo ci si concentrerà sull'uso di un sottoinsieme di tali metodi, nella convinzione che essi permettano di risolvere la stragrande maggioranza delle situazioni in modo compatto ed elegante.
Una finestra di conferma personalizzata si costruisce utilizzando il seguente metodo statico che ammette due forme:
int showConfirmDialog(Component parent,Object Message) int showConfirmDialog(Component parent,Object Message,String title,int optionType, int messageType)
Il metodo restituisce uno dei seguenti valori a seconda se il bottone premuto è rispettivamente Si , No , Annulla , Ok :
YES_OPTION, NO_OPTION, CANCEL_OPTION,OK_OPTION
che sono delle costanti definite nella classe JOptionPane. Una finestra di informazione personalizzata si costruisce con il seguente metodo statico che ammette due forme:
void showMessageDialog(Component parent,Object Message) void showMessageDialog(Component parent,Object Message,String title, int messageType)
Una finestra di input personalizzata si ottiene con il seguente metodo statico che ammette tre forme:
Object showInputDialog(Component parent,Object Message) Object showInputDialog(Component parent,Object MessageString title, int messageType) Object showInputDialog(Component parent,Object Message,String title, int messageType,Icon icon,Object[] SelectedValues, Object initialValue)
Corso di Progettazione del Software, A.A. 2004/ Docente: Massimo Mecella, tutor: Massimiliano de Leoni
è un componente che visualizza
no dei suoi costruttori è mostrato di seguito:
ct intCol[])
d tare e intCol è un array
llPane dove l’argomento del costruttore specifica la
n JScro quale si
Stato di residenza:","Selezione", JOptionPane.INFORMATION_MESSAGE,null,null,"Italia"); System.out.println(“Selezionato: “+prova); String x[]={"a","b","c","d","e","f","g"}; prova=(String)JOptionPane.showInputDialog(null, "Scegli l'opzione:","Selezione", JOptionPane.INFORMATION_MESSAGE, null,x, x[3]); System.exit(0); } }
Una tabella righe e colonne di dati. È possibile trascinare il cursore sui bordi delle colonne per ridimensionarle; è anche possibile trascinare una colonna in una nuova posizione. Le tabelle sono implementate dalla classe JTable.
JTable(Object dati[][],Obje
dove ati è un array bidimensionale delle informazione da presen monodimensionale con le intestazione delle colonne. Ecco i passi per utilizzare una tabella in un frame:
U llPane è un pannello di scorrimento che presenta un’area rettangolare nella può vedere un componente. Se il componente ha dimensione maggiore del pannello vengono fornite barre di scorrimento orizzontali e/o verticali.
Corso di Progettazione del Software, A.A. 2004/ Docente: Massimo Mecella, tutor: Massimiliano de Leoni
Esempio
import java.awt.; import javax.swing.;
public class Tabella extends JFrame { private JTable tab; private JScrollPane jsp;
public Tabella(Object dati[][],Object intCol[]) { this.getContentPane().setLayout(new BorderLayout()); tab=new JTable(dati,intCol); jsp=new JScrollPane(tab); this.getContentPane().add(jsp,BorderLayout.CENTER); }
public static void main(String args[]) { Object data[][]={ {"09109022","Paolo","Rossi"}, {"09109923","Diego Armando","Maradona"}, {"09090232","Jose","Altafini"}, {"09119923","Alex","Del Piero"}, {"09110232","Filippo","Inzaghi"}, {"09109923","Diego Armando","Maradona"}, {"09090232","Jose","Altafini"}, {"09109923","Diego Armando","Maradona"}, {"09090232","Jose","Altafini"} }; String intestazioni[]={"Numero di Matricola","Nome","Cognome"}; Tabella t=new Tabella(data,intestazioni); t.setSize(300,300); t.setVisible(true); } }
Corso di Progettazione del Software, A.A. 2004/ Docente: Massimo Mecella, tutor: Massimiliano de Leoni
Di seguito alcuni metodi che permettono di agire sul testo di una TextArea:
void setText(String s) Cancella il contenuto del pannello e lo rimpizza con s
String getText()
String getText(int offs,int len)
Restituisce il testo contenuto all’interno del componente. Se sono specificati i due parametri ne restituisce un sottoinsieme a partire dalla posizione offs e per len caratteri.
void insert(String str,int pos) Inserisce la stringa pos^ str^ nella posizione specificata da
void append(String str) Inserisce il contenuto della stringa in coda al documento.
Void replaceRange(String str, int start,int end)
Rimpiazza la sezione di testo compresa tra start e end con la stringa specificata
Un gruppo di metodi permette di conoscere la posizione attuale del cursore ed eventualmente modificarla; tra questi metodi ci sono anche quelli che permettono di operare direttamente sulla clipboard:
int getCaretPosition() Restituisce la posizione del cursore
void setCaretPosition(int pos) Sposta il cursore alla posizione specificata
void cut()
void copy()
void paste()
void selectAll()
Questi quattro metodi effettuano le operazioni sugli appunti. Il primo e il secondo effettuano le operazioni di taglia e copia sulla selezione effettua all’interno degli appunti. Il terzo inserisce nella posizione corrente del cursore all’interno della TextArea il contenuto degli appunti. L’ultimo metodo seleziona tutto il contenuto della TextArea
Corso di Progettazione del Software, A.A. 2004/ Docente: Massimo Mecella, tutor: Massimiliano de Leoni
A partire dal JDK 1.3, è possibile programmare attraverso le classi Timer e TimerTask un compito per un’esecuzione in un tempo futuro ad ogni intervallo di tempo specificato. Quando scade l’intervallo viene eseguito il compito. La classe Timer si utilizza per programmare l’esecuzione di un compito il quale è rappresentato da un’istanza di TimerTask. Quindi per programmare un compito è prima necessario creare un oggetto TimerTask e poi schedularne l’esecuzione futura utilizzando un’istanza di Timer. Tipicamente un compito si costruisce estendendo la classe TimerTask che definisce i seguenti due metodi:
void run() Contiene il codice per il timer task
boolean cancel() Terminadell’esecuzione del task viene impedita.^ l’esecuzione^ del^ compito.^ Restituisce^ true^ se^ la^ terminazione
Una volta che il task è stato creato ne viene programmato l’esecuzione futura attraverso un oggetto di tipo Timer. Questa classe definisce i seguenti metodi:
void cancel() Cancella la programmazione del compito.
void schedule(TimerTask T,long attesa) void schedule(TimerTask T,long attesa,int rip)
T viene programmato per essere eseguito dopo che è trascorso il tempo attesa e poi ripetuto (se specificato) a intervalli di durata rip. I parametri attesa e rip sono specificati in millisecondi.
Esempio
import java.util.*;
public class TTest extends TimerTask { String messaggio; int n; //rip è il numero di ripetizioni nella scrittura della data prima della //terminazione del programma int rip; public TTest(int aRip) { super(); n=1; rip=aRip; } public void run() { GregorianCalendar gc=new GregorianCalendar(); int hh=gc.get(Calendar.HOUR); int mm=gc.get(Calendar.MINUTE); int ss=gc.get(Calendar.SECOND); System.out.println("L'ora attuale è "+hh+":"+mm+":"+ss); if((n++)>rip) { this.cancel(); System.exit(0); }
Corso di Progettazione del Software, A.A. 2004/ Docente: Massimo Mecella, tutor: Massimiliano de Leoni
public PassaListener(JLabel aEtichetta) { etichetta=aEtichetta; originale=aEtichetta.getBackground(); }
public void MouseEntered(MouseEvent me) { etichetta.setBackground(Color.red); }
public void MouseExited(MouseEvent me) { etichetta.setBackground(originale); } }
La convenzione JAVA nella nomenclatura delle classi prevede un file Java per ogni classe pubblica dell’applicazione (in particolare il file dovrà avere lo stesso nome della classe che definisce). Inoltre, qualora si definiscano package, ognuno di questi corrisponde nel File System ad una directory separata. Tipicamente una applicazione complessa può arrivare ad avere anche decine di classi che possono essere suddivise in package per semplificarne la ricerca; senza contare che le classi stesse potrebbero utilizzare file musicali, file immagine ed altri tipi di risorse che ovviamente devono essere distribuiti unitamente ai file .class. Ciò vuol dire che un progetto potrebbe contenere moltissimi file e ciò può complicare non poco l’invio e l’installazione di software. Proprio a questo scopo, il linguaggio Java ha introdotto il concetto di Java Archiver (JAR). Un file JAR permette di disporre in modo efficace un set di classi e le risorse ad esse associate in un unico file. La tecnologia JAR può quindi semplificare non poco la distribuzione di una applicazione. Dal punto di vista puramente tecnico, un file JAR non è altro che un file ZIP contenente i file dell’applicazione. All’interno dei file JAR chiaramente i file devono essere organizzati secondo la stessa struttura di file e directory che hanno quando sono decompressi sul disco. Ad esempio se un progetto consta di 5 file: a.class, b.class, c.class, d.class e e.gif raggruppati all’interno di una stessa directory, il file JAR(cioè il file ZIP) dovrà contenere compressi gli stessi file disposti nell’ipotetica radice del file JAR. Per creare un file JAR, quindi, si può tranquillamente utilizzare un prodotto per la gestione dei file compressi (tipo Winzip ) e poi successivamente rinominare il file .zip in file .jar. In alternativa, se non si è in possesso di nessun compressore ZIP si può utilizzare l’utilità jar messa a disposizione dal JDK. Una volta che è stato creato un JAR è possibile far “girare” l’applicazione semplicemente nel modo seguente:
java –cp [nome_jar] [class_main]
dove nome_jar è il nome del file JAR (compreso l’estensione .jar) e class_main è la classe che ha definito il metodo main. Sebbene questo metodo è sicuramente migliore di avere moltissimi file sparsi, sarebbe meglio che un ipotetico utente non debba sapere nulla sulla classe che definisce il main. Ciò si può realizzare definendo il file manifesto che specifica informazioni aggiuntive. Tale file deve necessariamente chiamarsi MANIFEST.MF e si deve trovare nella sottodirectory META-INF del file JAR.
Corso di Progettazione del Software, A.A. 2004/ Docente: Massimo Mecella, tutor: Massimiliano de Leoni
Un tipico esempio di file manifesto per specificare la classe con il main è il seguente:
Manifest-Version: 1. Created-By: 1.4.0_01 (Sun Microsystems Inc.) Main-Class: [class_main]
A questo punto per far “girare” l’applicazione è sufficiente scrivere
java –jar [nome_jar]
Il Java permette di conoscere l’ora e la data corrente attraverso la classe GregorianCalendar del package java.util costruendone un’istanza a partire dal costruttore senza parametri. Il metodo più comunemente usato di questa classe è
int get(int campoCalendar)
che restituisce il valore di uno dei componente dell’oggetto chiamante. Il componente è indicato come parametro campoCalendar. Alcuni dei componenti che possono essere richiesti sono i seguenti:
Calendar.YEAR (^) Restituisce l’anno (corrente). Calendar.MONTH (^) Restituisce il mese (corrente). Tale valore va da 0 a 11. Calendar.DAY_OF_MONTH (^) Restituisce il giorno del mese (corrente). Calendar.HOUR_OF_DAY (^) Restituisce l’ora (corrente). Calendar.MINUTE (^) Restituisce il minuto (corrente). Calendar.SECOND (^) Restituisce il secondo (corrente).
Esempio
import java.util.*;
public class Application { public static void main(String args[]) { GregorianCalendar cal=new GregorianCalendar(); int aa=cal.get(Calendar.YEAR); int mm=cal.get(Calendar.MONTH)+1; int gg=cal.get(Calendar.DAY_OF_MONTH); System.out.print(“Oggi è il giorno “+gg); System.out.println(“ del mese “+mm+” anno “+aa); } }
Corso di Progettazione del Software, A.A. 2004/ Docente: Massimo Mecella, tutor: Massimiliano de Leoni
metodo get o gli iteratori, si realizzare il necessario successivo cast (come alla riga 7). Questo perché i metodi di LinkedList prendono in ingresso e restituiscono Object. La Sun ha pensato bene a tal proposito di introdurre a partire dalla versione 1.5 il concetto di generics. I generics sfruttano il fatto che il programmatore nella maggior parte dei casi sa quale tipo di oggetti sono inseriti in una particolare lista. Nel codice questa conoscenza è evidente dalla presenza di un cast specifico. Tuttavia, quando questa conoscenza non è presente, come già detto, è possibile che venga generato un errore a run-time sul cast. I generics sono dei parametri speciali racchiusi tra un minore e un maggiore che possono seguire i riferimenti e i costruttori delle classi del Collection Framework (e quindi anche LinkedList) e che sono usati per specificare il tipo di oggetti che quell’oggetto del Collection Framework può collezionare. Ecco il frammento del codice di sopra che sfrutta i generics :
LinkedList
Si noti la definizione della lista myIntList: viene specificato che non solo è una LinkedList ma in particolare che è una LinkedList di Integer. In questo frammento alla riga 7 il cast non è più presente perché non necessario dato che il compilatore già sa che l’oggetto restituito è di tipo Integer poiché la lista, usando in generics , è dichiarata essere di oggetti Integer. Si potrebbe pensare che l’unica differenza è che il cast alla riga 7 è come se fosse stato spostato alla riga 1 ma non è così: la differenza è grande. Il compilatore in questo modo è in grado di verificare e garantire la correttezza degli oggetti aggiunti alla lista nella riga 3 a tempo di compilazione. In altre parole si ha la certezza che la lista manterrà sempre oggetti di tipo Integer. Il cast, infatti, dice solo al compilatore qualcosa che il programmatore pensa sia vero ad un certo momento dell’esecuzione. L’effetto, specialmente nei grandi programmi, è una maggiore leggibilità e robustezza. Un altro tipo di warning introdotto a partire dalla versione 1.5 riguarda le classi che implementano l’interfaccia Serializable. Il compilatore associa ad ogni classe serializzabile un numero di versione, chiamato serialVersionUID, che è usato durante la deserializzazione per verificare che l’oggetto letto da file è compatibile con quello definito all’interno dell’applicazione. Se la classe caricata per quello oggetto ha un differente serialVersionUID rispetto a quello che ci si aspettava, significa che l’oggetto letto è incompatibile e quindi verrà lanciata una InvalidClassException. Una classe serializzabile può definire esplicitamente il proprio serialVersionUID esplicitamente definendo un campo statico di nome "serialVersionUID" di tipo long:
modificatore_di_accesso static final long serialVersionUID = valore ;
Se una classe serializzabile non dichiara esplicitamente un serialVersionUID allora il compilatore calcolerà un valore di default per quella classe basandosi su vari aspetti della classe su cui in questa sede non entreremo in dettaglio. È comunque fortemente raccomandato che tutte le classi serializzabili esplicitamente dichiarino un serialVersionUID poiché il valore di default è altamente sensibile ai dettagli della classe e può variare con la versione del compilatore. Il risultato è di ottenere inaspettate InvalidClassExceptions durante le deserializzazioni. Per questa
Corso di Progettazione del Software, A.A. 2004/ Docente: Massimo Mecella, tutor: Massimiliano de Leoni
ragione, per garantire consistenti valori di serialVersionUID tra differenti compilatori java su diverse piattaforme, occorre dichiarare esplicitamente un valore. A partire dal JDK 1.5, se serialVersionUID non viene esplicitamente definito, il compilatore restituisce un Serializable warning. La Sun suggerisce di dichiarare privato il modificatore della variabile definita esplicitamente quando è possibile perché altrimenti si applicherebbe non solo alla classe dichiarata nell’immediato ma anche in futuro ad eventuali classi derivate.