Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
1
Utilizzo delle classi di base fornite dal JDK
Con questa sessione iniziamo la parte un po pi pratica del corso. Man mano che andremo avanti le sessioni assumeranno
sempre pi un carattere pratico basato su esempli applicativi.
Iniziamo questa sessione partendo da esempi di utilizzo di alcune classi di base fornite dal JDK. La maggior parte di queste classi
si trova nei package java.lang e java.util.
In gergo Java si parla di classi wrapper quando si fa riferimento a classi che incapsulano (wrap) al loro interno altre classi
oppure, come in questo caso, dei tipi primitivi.
Per ciascuno degli 8 tipi primitivi visti nelle prime sessioni del corso esiste lequivalente classe wrapper.
2
Per esempio, dato il tipo primitivo int troveremo nel package java.lang la classe Integer.
Si tratta di una classe costruita attorno al tipo primitivo e che serve a trasformare in oggetto un dato primitivo.
Esempio:
int numeroPrimitivo = 1;
E una best practice (pratica consigliata), utilizzare sempre gli oggetti wrapper dei tipi primitivi come attributi di una classe ed
utilizzare i tipi primitivi solo come variabili dappoggio, temporanee, come per esempio nei contatori di un ciclo for oppure se si
vuole effettuare un semplice calcolo.
Guardano le API della classe Integer attraverso la JavaDoc possiamo osservare tutto ci che si pu fare con un oggetto Integer.
Esempio:
package com.azienda.esempiCorso.sessione7.wrapperPrimitivi;
3
int primitiveValue = oggetto.intValue();
System.out.println("Wrapper intero: " + oggetto);
System.out.println("Wrapper intero: " + oggetto.toString());
System.out.println("Primitive value: " + primitiveValue);
int maxValueIntero = Integer.MAX_VALUE;
int minValueIntero = Integer.MIN_VALUE;
System.out.println("Massimo valore intero: " + maxValueIntero);
System.out.println("Minimo valore intero: " + minValueIntero);
Integer oggetto2 = new Integer("20");
int compareResult = oggetto.compareTo(oggetto2);
if ( compareResult > 0 )
{
System.out.println(oggetto + " maggiore di " + oggetto2);
}
else if ( compareResult == 0 )
{
System.out.println(oggetto + " uguale a " + oggetto2);
}
else
{
System.out.println(oggetto + " minore di " + oggetto2);
}
String numeroComeStringa = "30";
try
{
4
int stringaParsata = Integer.parseInt(numeroComeStringa);
}
catch (Exception ex)
{
System.out.println("La stringa " + numeroComeStringa + " non rappresenta un numero");
}
numeroComeStringa = "Paolo";
try
{
5
Loutput a video sar:
Wrapper intero: 10
Wrapper intero: 10
Primitive value: 10
Massimo valore intero: 2147483647
Minimo valore intero: -2147483648
10 minore di 20
La stringa Paolo non rappresenta un numero
Lesempio mostra come viene costruito un oggetto Integer sia a partire da un primitivo int che da una stringa ed alcuni metodi di
utilit della classe Integer.
lequivalenza tra la stampa a video delloggetto oggetto e del metodo oggetto.toString(). Quando la JVM trasforma un
oggetto in String, come nel caso in cui proviamo a stamparlo a video, invoca il metodo toString() delloggetto
lutilizzo degli attributi static MAX_VALUE e MIN_VALUE tramite la sintassi nomeClasse.attributo al posto di
nomeOggetto.attributo; lo stesso dicasi per il metodo static parseInt()
6
la gestione delle eccezioni nella chiamata al metodo parseInt()
Gli stessi concetti appena esposti per la coppia tipo primitivo-classe wrapper int->Integer, valgono anche per gli altri 7 tipi
primitivi:
Anche per gli altri 7 tipi primitivi abbiamo quindi le corrispondenti classi wrapper, sempre allinterno del package java.lang, che
avranno lo stesso nome dei tipi primitivi eccetto la prima lettera in maiuscolo. Quindi, anche per queste altre 7 classi wrapper
invitiamo a guardare le API descritte nella JavaDoc.
7
Classe String
Una classe che merita una trattazione a parte la classe String visto il suo vastissimo utilizzo e la moltitudine di metodi che
mette a disposizione.
Abbiamo gi visto nelle sessioni precedenti diversi utilizzi di oggetti di tipo String anche se ci siamo sempre limitati soltanto ad
inizializzare una stringa ed a stamparla al video. Lunica operazione differente che abbiamo visto quella di concatenazione di
stringhe tramite loperatore +.
Apriamo le API della classe String, package java.lang, per vedere attraverso la JavaDoc le funzionalit presenti.
Di seguito un esempio di codice sorgente che mostra luso di alcuni dei metodi pi comuni della classe String:
package com.azienda.esempiCorso.sessione7.stringhe;
8
int lunghezza = s.length();
System.out.println("La lunghezza della stringa '" + s + "' " + lunghezza);
char caratterePosizione0 = s.charAt(0);
System.out.println("Nella stringa '" + s + "' il carattere in posizione 0 " + caratterePosizione0);
for ( int i=0; i<s.length(); i++ )
{
char caratterePosizioneI = s.charAt(i);
System.out.println("Nella stringa '" + s + "' il carattere in posizione " + i + " " + caratterePosizioneI);
}
int primaPosizioneC = s.indexOf("C");
System.out.println("Nella stringa '" + s + "' la prima posizione del carattere C " + primaPosizioneC);
int primaPosizioneCMinuscolo = s.indexOf("c");
System.out.println("Nella stringa '" + s + "' la prima posizione del carattere c (minuscolo) " +
primaPosizioneCMinuscolo);
String s1 = "dado";
int primaPosizioneD = s1.indexOf("d");
System.out.println("Nella stringa '" + s1 + "' la prima posizione del carattere d " + primaPosizioneD);
int ultimaPosizioneD = s1.lastIndexOf("d");
System.out.println("Nella stringa '" + s1 + "' l'ultima posizione del carattere d " + ultimaPosizioneD);
boolean contieneAMinuscolo = s.contains("a");
System.out.println("La stringa '" + s + "' contiene il carattere a (minuscolo)? " + contieneAMinuscolo);
boolean contieneAMaiuscolo = s.contains("A");
System.out.println("La stringa '" + s + "' contiene il carattere A (maiuscolo)? " + contieneAMaiuscolo);
String stringaMaiuscola = s.toUpperCase();
System.out.println("La stringa '" + s + "' in maiuscolo diventa: " + stringaMaiuscola);
String stringaMinuscola = s.toLowerCase();
9
System.out.println("La stringa '" + s + "' in minuscolo diventa " + stringaMinuscola);
String s3 = "Bianco";
String s4 = "bianco";
boolean s3UgualeS4 = s3.equals(s4);
System.out.println("'" + s3 + "' uguale a '" + s4 + "'? " + s3UgualeS4);
boolean s3UgualeS4CaseInsensitive = s3.equalsIgnoreCase(s4);
System.out.println("'" + s3 + "' uguale a '" + s4 + "' senza distinzioni tra maiuscole e minuscole ? " +
s3UgualeS4CaseInsensitive);
System.out.println("'" + s3 + "' inizia con 'Bia' ? " + s3.startsWith("Bia"));
System.out.println("La sottostringa di '" + s3 + "' a partire dal terzo carattere " + s3.substring(2));
System.out.println("La sottostringa di '" + s3 + "' compresa tra terzo e quinto carattere " + s3.substring(2,4));
String s5 = "";
System.out.println("La stringa '" + s5 + "' vuota? " + s5.isEmpty());
String s6 = " ";
System.out.println("La stringa '" + s6 + "' vuota? " + s6.isEmpty());
String s7 = "c_i_a_o";
String [] arrayElementiS7 = s7.split("\\_");
System.out.println("Ciclo for sui singoli caratteri della stringa '" + s7 + "' suddivisa con lo split sul carattere '_'");
for ( int i=0; i<arrayElementiS7.length; i++ )
{
System.out.println("s[" + i + "]: " + arrayElementiS7[i]);
}
String s8 = "passo";
String s9 = s8.replaceAll("s","t");
System.out.println("Nella stringa '" + s8 + "' sostituendo le s con le t otteniamo: " + s9);
String s11 = " Java un linguaggio di programmazione ad oggetti ";
10
String s12 = s11.trim();
System.out.println("Rimuovendo dalla stringa '" + s11 + "' gli spazi bianchi iniziali e finali si ottiene: \n'" + s12 +
"'");
}
}
11
'Bianco' uguale a 'bianco' senza distinzioni tra maiuscole e minuscole ? true
'Bianco' inizia con 'Bia' ? true
La sottostringa di 'Bianco' a partire dal terzo carattere anco
La sottostringa di 'Bianco' compresa tra terzo e quinto carattere an
La stringa '' vuota? true
La stringa ' ' vuota? false
Ciclo for sui singoli caratteri della stringa 'c_i_a_o' suddivisa con lo split sul carattere '_'
s[0]: c
s[1]: i
s[2]: a
s[3]: o
Nella stringa 'passo' sostituendo le s con le t otteniamo: patto
Rimuovendo dalla stringa ' Java un linguaggio di programmazione ad oggetti ' gli spazi bianchi iniziali e finali si ottiene:
'Java un linguaggio di programmazione ad oggetti'
Classe StringBuffer
Per prima cosa apriamo la JavaDoc per controllare le API della classe.
Anche la classe StringBuffer, come la classe String, viene utilizzata per lavorare con le stringhe. In genere StringBuffer viene
utilizzata quando si lavora con stringhe che verranno modificate frequentemente e si vuole ottimizzare lutilizzo della memoria.
12
String s = Ciao;
s = come va?;
stiamo sprecando memoria, nel senso che le due istruzioni allocano due aree di memoria distinte. Viceversa, scrivendo:
stiamo ottimizzando lutilizzo di memoria, poich viene allocata ununica area di memoria.
Da un oggetto di classe StringBuffer possiamo sempre recuperare lequivalente String con il metodo toString():
String s1 = s.toString();
Allinterno del package java.util troviamo una serie di classi di utilit messe a disposizione dal JDK. Alcune di queste classi sono
di utilizzo molto frequente nello sviluppo di qualsiasi progetto Java. Andiamo ad analizzare alcune di queste classi, come al solito
col supporto della JavaDoc delle API, degli esempi e dei video forniti nel corso.
13
Interfaccia Collection
Collection uninterfaccia che rappresenta una generica collezione di oggetti. Il concetto abbastanza simile a gi quello visto
per gli array, con la differenza che linterfaccia Collection espone una serie di metodi di utilit che non sono presenti negli array.
Osservando le API dellinterfaccia, attraverso la JavaDoc, si pu riscontrare la moltitudine di metodi messi a disposizione da
Collection.
Le principali classi concrete che implementano linterfaccia Collection che andremo adesso ad esaminare sono: ArrayList e
HashSet.
Classe ArrayList
Aprendo la JavaDoc possiamo subito osservare che ArrayList implementa diverse interfacce, in particolare Collection e List.
In gergo Java si parla di liste facendo riferimento ad oggetti di classi che implementano linterfaccia List, come appunto per gli
oggetti di classe ArrayList.
14
Da notare che viene specificato il tipo di oggetti che la lista dovr contenere tramite le parentesi angolari: nellesempio <String>,
ovvero stiamo dichiarando una lista di stringhe.
Gli oggetti vengono inseriti nella lista tramite invocazione del metodo add, come nellesempio che segue:
Nelle versioni di Java precedenti alla 5, in fase di dichiarazione di un oggetto lista si poteva omettere il tipo di oggetti della lista e
successivamente si potevano inserire nella lista anche oggetti di classe differente. In questo modo:
Dalla versione 5 in poi questa pratica ancora ammessa ma sconsigliata (il compilatore segnala un warning in fase di
compilazione).
15
Quando si aggiungono elementi alla lista invocando il metodo add, gli oggetti vengono inseriti in ordine partendo dallelemento
in posizione 0.
Quindi nellesempio precedente, stiamo inserendo nella lista, in posizione 0 la stringa Ciao ed in posizione 1 la stringa come
va?.
Gli oggetti possono essere rimossi dalla lista invocando il metodo remove; mentre per leggere gli oggetti dalla lista si usa il
metodo get specificando la posizione delloggetto che si vuole leggere.
package com.azienda.esempiCorso.sessione7.collection;
import java.util.ArrayList;
import java.util.List;
16
System.out.println("Stampa della lista dopo la remove di 'Ciao'");
stampaList(list);
}
17
Interfaccia Iterator
Introduciamo uninterfaccia che, anche se non fa parte della gerarchia di classi figlie di Collection, viene spesso utilizzata dalle
classi che stiamo esaminando.
Iterator rappresenta un cursore, una sorta di puntantore che si muove spostandosi (appunto iterando) sugli elementi di una lista
o di una mappa.
Guardando la JavaDoc delle API di Iterator, vediamo che linterfaccia espone solo 3 metodi:
next() per accedere alloggetto corrente puntato dal cursore e muovere il cursore sulloggetto successivo
hasNext() per controllare che esistano altri oggetti nella Collection
remove() per rimuovere dalla Collection loggetto puntato dal cursore
Viene utilizzato quando si vuole iterare sugli elementi di un oggetto di tipo Collection, in modo analogo a quando abbiamo visto
nel precedente col metodo stampaList. L abbiamo iterato sugli oggetti della lista usando il ciclo for e leggendo i singoli oggetti
della lista tramite il metodo get. Ecco una versione equivalente del metodo che usa invece linterfaccia Iterator:
private static void stampaListWithIterator(List<String> list){
Iterator<String> iterator = list.iterator();
int i = 0;
while ( iterator.hasNext() )
{
String item = iterator.next();
System.out.println("Oggetto in posizione " + i + " " + item);
18
i++;
}
}
Classe HashSet
Osservando la JavaDoc delle API della classe HashSet, notiamo che la classe implementa diverse interfacce, in particolare
Collection e Set.
Un oggetto di tipo Set simile ad un oggetto List, ma con alcune differenze.
19
Innanzitutto non garantito che lordine di inserimento corrisponda allordinamento allinterno del Set: aggiungendo due
elementi nel Set non garantito che il primo elemento sia inserito prima del secondo (come vedremo tra poco, quando
necessario garantire lordine di inserimento si usa la classe LinkedHashSet). Inoltre, nel Set non sono ammessi duplicati.
Facciamo un confront tra le due classi aiutandoci con un esempio:
List<String> list = new ArrayList<String>();
list.add(Ciao);
list.add(Ciao);
Il codice appena scritto crea una lista di due stringhe uguali, la prima in posizione 0 e la seconda in posizione 1.
Se scriviamo:
Set<String> set = new HashSet<String>();
set.add(Ciao);
set.add(Ciao);
il codice appena scritto crea un set di una sola stringa Ciao la cui posizione non garantito che sia 0.
Inoltre in una classe di tipo Set non presente il metodo get; pertanto, per leggere gli oggetti contenuti nel set occorre prima
ottenere un iterator e poi scorrere questultimo, come nel seguente esempio:
20
package package com.azienda.esempiCorso.sessione7.collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
21
{
String item = iterator.next();
System.out.println("Elemento in posizione " + i + ": " + item);
i++;
}
}
Classe LinkedHashSet
Per la classe LinkedHashSet valgono le stesse considerazioni fatte per HashSet, salvo il fatto che, come detto, la classe
LinkedHashSet garantisce che lordinamento di inserimento sia rispettato.
22
Classe HashMap
Osservando le APl della classe JavaDoc osserviamo subito che la classe HashMap implementa diverse interfacce, in particolare
linterfaccia Map.
Una mappa, in Java, una struttura a due livelli chiave-valore. Ovvero, ogni elemento della mappa costituito da una coppia di
oggetti, di cui il primo funge da chiave per accedere al secondo (il valore).
Facciamo subito un esempio:
package com.azienda.esempiCorso.sessione7.maps;
import java.util.HashMap;
import java.util.Map;
23
Loutput a video :
Il valore : Ciao
Lesempio mostra come inserire la coppia chiave-valore tramite il metodo put e come recuperare un valore a partire da una chiave
tramite il metodo get.
Come si pu vedere dalle API della JavaDoc, linterfaccia Map espone diversi metodi. In particolare notiamo keySet() che
restituisce il Set di tutte le chiavi della mappa edi metodo values() che resituisce la Collection di tutti i valori inseriti nella mappa.
Vediamo di seguito un esempio di codice che effettua linserimento di 5 coppie chiave-valore nella mappa e poi effettua la
stampa a video delle coppie.
package com.azienda.esempiCorso.sessione7.maps;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
24
public class EsempioHashMap2 {
25
String valore = mappa.get(chiave);
System.out.println("Valore: " + valore);
i++;
}
}
Valore: Stringa 0
Valore: Stringa 1
Valore: Stringa 2
Valore: Stringa 3
Valore: Stringa 4
Da notare che la mappa gestisce linsieme delle chiavi come un Set e questo vuol dire che non sono ammesse chiavi duplicate
(abbiamo visto che Set non consente duplicati).
26
Da notare anche che HashMap, cos come HashSet, non garantisce lordinamento in inserimento, ovvero lordine di inserimento
non detto che coincida con lordine allinterno della mappa. Nel caso occorra garantire la corrispondenza tra ordine di
inserimento e posizioni allinterno della mappa occorre usare LinkedHashMap.
Classe LinkedHashMap
Come detto lequivalente di HashMap da usare quando necessario preservare lordine di inserimento anche nel
posizionamento degli oggetti allinterno della mappa.
Guardiamo nel codice desempio il metodo creaMappa e notiamo che nella firma abbiamo dichiarato di restituire un oggetto di
tipo Map e non HashMap, nonostante nel corpo del metodo abbiamo creato un oggetto di classe HashMap. Teoricamente
avremmo potuto anche cambiare la firma del metodo dichiarando di restituire un HashMap, ma sarebbe stato un errore: se, infatti
in futuro avessimo deciso di cambiare il corpo del metodo e di creare un oggetto LinkedHashMap, perch magari sono cambiati i
requisiti del sistema e dobbiamo garantire lordinamento in inserimento, avremmo dovuto cambiare tutte le chiamate del codice
27
esterno che utilizzava il metodo creaMappa. Viceversa, per come abbiamo scritto la firma, basterebbe cambiare una sola riga di
codice nel corpo del metodo :
al posto di
Due classi molto usate del package java.util sono Date e Calendar.
Date, come suggerisce il nome viene usata per rappresentare le date, mentre Calendar una classe di utilit che viene usata in
coppia con Calendar.
Come al solito apriamo la JavaDoc per guardare le API delle due classi.
28
Con questa semplice istruzione abbiamo creato un oggetto data che rappresenta la data odierna. Da notare che la data e lora
fanno riferimento a quelle del sistema operativo del computer sui cui mandiamo in esecuzione il programma.
Se provassimo a stampare a video loggetto data, come sappiamo, la JVM richiamerebbe il metodo toString() per convertire la
data in stringa e otterremmo qualcosa del tipo :
Se volessimo stampare qualcosa di pi facile lettura potremmo utilzzare la classe Calendar come nellesempio che segue :
package com.azienda.esempiCorso.sessione7.date;
import java.util.Calendar;
import java.util.Date;
29
int mese = calendar1.get(Calendar.MONTH) + 1;
int anno = calendar1.get(Calendar.YEAR);
System.out.println("Oggi il: " + giornoDelMese + "/" + mese + "/" + anno);
}
Loutput a video :
Come si pu osservare dalle API della JavaDoc, i metodi messi a disposizione dalla coppia di classi Date e Calendar sono molti,
e ci permettono di manipolare in tantissimi modi le date, di confrontare date tra di loro etc..
Per rappresentare in una forma ancora pi snella e leggibile una data si pu utilizzare la classe SimpleDateFormat del package
java.text.
30
package com.azienda.esempiCorso.sessione7.date;
import java.text.SimpleDateFormat;
import java.util.Date;
31
}
Output a video :
Stampa della data tramite chiamata della JVM al metodo toString: Fri Sep 18 18:42:26 CEST 2015
Stampa della stringa dopo conversione con SimpleDateFormat: 18/09/2015
Riotteniamo la data originale dal SimpleDateFormat: Fri Sep 18 00:00:00 CEST 2015
Notiamo come lultima stampa, rispetto alla prima abbia perso le informazioni relative allora, ai minuti ed ai secondi. Questo
perch abbiamo usato un SimpleDateFormat con pattern dd/MM/yyyy, ovvero giorno/mese/anno. Se avessimo voluto conservare
anche le altre informazioni relative allorario avremmo dovuto istanziare il SimpleDateFormat con il seguente pattern:
dd/MM/yyyy HH:mm:ss
Di seguito lesempio :
package com.azienda.esempiCorso.sessione7.date;
import java.text.SimpleDateFormat;
import java.util.Date;
32
public class EsempioSimpleDateFormat2 {
33
Ed il relativo output a video :
Stampa della data tramite chiamata della JVM al metodo toString: Fri Sep 18 18:46:34 CEST 2015
Stampa della stringa dopo conversione con SimpleDateFormat: 18/09/2015 18:46:34
Riotteniamo la data originale dal SimpleDateFormat: Fri Sep 18 18:46:34 CEST 2015
Nei computer esistono una serie di simboli alfanumerici che, pur avendo lo stesso significato, vengono rappresentati in modo
differente in base alla nazione. Si pensi ad esempio, nel caso dei numeri, al separatore delle cifre decimali o al separatore delle
migliaia.
In Italia, si usa come simbolo per rappresentare il separatore dei decimali il carattere , (virgola), mentre il simbolo . (punto)
viene utilizzato come separatore di migliaia. Ad esempio, in Italia per indicare che un prodotto costa mille euro e cinquanta
centesimi, scriveremmo: 1.000,50.
Negli Stati Uniti, invece, esattamente lopposto: il simbolo usato come separatore dei decimali il . (punto) ed il simbolo
usato come separato di migliaia , (virgola). La stessa informazione dellesempio precedente, negli Stati Uniti sarebbe
rappresentata come 1,000.50 .
34
La classe Locale, del package java.util, in Java rappresenta una nazione, nel senso dellinsieme dei simboli utilizzati in una
determinata nazione. Impostando quindi un determinato Locale in un programma Java stiamo informando la JVM di voler
utilizzare i simboli grafici tipici di quel Locale.
In Java esiste sempre un Locale di default, ovvero il Locale utilizzato dalla JVM in mancanza di unimpostazione esplicita da
parte del programmatore.
Il Locale di default determinato dalle impostazioni della lingua del sistema operativo del computer sul quale viene fatto girare il
programma Java.
NumberFormat la classe del package java.text che gioca per i numeri lo stesso ruolo che SimpleDateFormat gioca per le date
(cfr esempio sulle date). Non a caso entrambe le classi fanno parte dello stesso package: java.text. La classe NumberFormat aiuta
quindi a rappresentare un numero in un particolare formato che determinato dal Locale che il programma Java sta utilizzando.
Esempio:
package com.azienda.esempiCorso.sessione7.NumeriELocale;
import java.text.NumberFormat;
import java.util.Locale;
35
public class EsempioNumeriLocale {
public static void main(String[] args)
{
double d = 123000.55;
System.out.println("Numero double senza nessuna formattazione: " + d);
String s = NumberFormat.getInstance().format(d);
System.out.println("Numero double con formattazione data dal Locale di default del mio pc (Italiano): " + s);
String s1 = NumberFormat.getInstance(Locale.US).format(d);
System.out.println("Numero double con formattazione data dal Locale americano: " + s1);
}
Output a video:
Da notare
listanziazione di un Locale tramite istruzione Locale.US. La classe Locale, infatti, espone una serie di costanti predefinite
che rappresentano degli oggetti Locale gi pronti (controllare la JavaDoc delle API di Locale)
listanziazione di un oggetto di classe NumberFormat tramite istruzione NumberFormat.getInstance(Locale.US)
36
linvocazione al volo del metodo format sulloggetto NumberFormat istanziato. In pratica, nella stessa istruzione
abbiamo istanziato loggetto ed invocato il metodo; questo, anche perch non ci interessava conservare un riferimento alloggetto
non dovendolo usare successivamente nel programma
37