Il linguaggio Java: aggiunte in Java 1.5

annuncio pubblicitario
……………………………………………………………………..
Il linguaggio Java:
aggiunte in Java 1.5
Una breve presentazione
F. Damiani - Alg. & Lab. 04/05 (da A. Martelli - P.in Rete & L. 04/05)
GENERICI
Java 1.5 introduce i generici: classi che hanno un parametro di
tipo.
Nelle versioni precedenti a Java 1.5 si può definire:
List miaLista = new LinkedList();
miaLista.add(new(Integer(0));
Integer x = (Integer)miaLista.iterator().next();
Gli oggetti List possono contenere oggetti di qualunque tipo, e
quindi quando si estrae un oggetto dalla lista è necessario fare il
cast.
F. Damiani - Alg. & Lab. 04/05 (da A. Martelli - P.in Rete & L. 04/05)
Nella nuova versione:
List<Integer> miaLista = new LinkedList<Integer>();
miaLista.add(new(Integer(0));
Integer x = miaLista.iterator().next();
La miaLista può contenere solo oggetti Integer.
Non è più necessario il cast nell'ultima istruzione: il
compilatore sa che l'oggetto estratto è un Integer.
F. Damiani - Alg. & Lab. 04/05 (da A. Martelli - P.in Rete & L. 04/05)
L'interface List è specificata nel package java.util come:
public interface List<E> {
void add(E x);
....
}
Quando si dichiara una variabile di tipo List<Integer>, il
parametro formale E viene legato ad Integer.
E' come se si usasse una nuova interface:
public interface ListofInteger {
void add(Integer x);
....
F. Damiani - Alg. & Lab. 04/05 (da A. Martelli - P.in Rete & L. 04/05)
}
Esempio
In realtà la dichiarazione di un generico come List<Integer>
non viene espansa come detto prima, cioè non vengono create
copie multiple del codice di List, una per ogni valore del
parametro.
La dichiarazione di List<E> viene compilata una volta per tutte
e genera un solo file class, come qualunque altra dichiarazione di
classe o interfaccia.
F. Damiani - Alg. & Lab. 04/05 (da A. Martelli - P.in Rete & L. 04/05)
Esempio
public class Pila<T>
{
private LinkedList<T> list = new LinkedList<T>();
public boolean isEmpty()
{return list.isEmpty();}
public void push(T v)
{
list.addFirst(v);}
public T pop()
{return list.removeFirst();}
public static void main(String[] args)
{
Pila<String> stack = new Pila<String>();
stack.push("a");
stack.push("bcd");
String s1 = stack.pop();
String s2 = stack.pop();
System.out.println(s1);
System.out.println(s2);
}
}
F. Damiani - Alg. & Lab. 04/05 (da A. Martelli - P.in Rete & L. 04/05)
GENERICI E SOTTOTIPI
Con gli array è possibile scrivere:
String[] as = new String[5];
Object[] ao = as;
ao[0] = new Object();
il compilatore accetta questo programma, ma l'inteprete dà errore
a runtime perché non si può assegnare un Object a un array di
stringhe. Viceversa in
List<String> ls = new ArrayList<String>();
List<Object> lo = ls;
lo.add(new Object());
la seconda istruzione non è accettata dal compilatore, perché
l'interprete non sarebbe in grado di scoprire l'errore a runtime nella
istruzione successiva.
F. Damiani - Alg. & Lab. 04/05 (da A. Martelli - P.in Rete & L. 04/05)
Il comportamento descritto prima è molto restrittivo. Ad esempio, il
seguente metodo per stampare gli elementi di una collezione:
void printCollection(Collection<Object> c)
Iterator<Object> i = c.iterator();
for(k=0; k<c.size(); k++)
System.out.println(i.next());
}
{
può essere usato solo per stampare gli elementi di una
Collection<Object>, ma non può avere come parametro, ad
esempio, una Collection<Integer>.
F. Damiani - Alg. & Lab. 04/05 (da A. Martelli - P.in Rete & L. 04/05)
Per definire una collection di qualunque cosa si può usare la
notazione Collection<?>.
void printCollection(Collection<?> c)
Iterator<?> i = c.iterator();
for(k=0; k<c.size(); k++)
System.out.println(i.next());
}
{
Tuttavia, in
Collection<?> c = new ArrayList<String>();
c.add(new Object());
il compilatore accetta la prima istruzione, ma non la seconda,
perché non può garantire la correttezza del tipo dell'elemento
che viene inserito nella collezione.
F. Damiani - Alg. & Lab. 04/05 (da A. Martelli - P.in Rete & L. 04/05)
FOR EACH
L'iterazione sulle collezioni mediante un Iterator è abbastanza
noiosa da scrivere. JDK 1.5 introduce al suo posto una nuova
istruzione for. Invece di:
void printCollection(Collection<Object> c)
Iterator<Object> i = c.iterator();
for(int k=0; k<c.size(); k++)
System.out.println(i.next());
}
{
si può scrivere:
void printCollection(Collection<Object> c)
for(Object e : c)
System.out.println(e);
}
{
F. Damiani - Alg. & Lab. 04/05 (da A. Martelli - P.in Rete & L. 04/05)
LIMITAZIONI SUL “?”
Consideriamo la classe astratta:
public abstract class Forma {
public abstract void disegna();
}
e diverse sue sottoclassi come Cerchio, Rettangolo, ... che
implementano il metodo disegna. Un metodo per disegnare le
forme contenute in una lista potrebbe essere:
public void disegnaTutto(List<Forma> forme) {
for (Forma f: forme)
f.disegna();
}
F. Damiani - Alg. & Lab. 04/05 (da A. Martelli - P.in Rete & L. 04/05)
La definizione
public void disegnaTutto(List<Forma> forme) {
è restrittiva, perché il metodo disegnaTutto può essere applicato
solo a una List<Forma> e non, per esempio, a una
List<Rettangolo>.
D'altra parte
public void disegnaTutto(List<?> forme) {
sarebbe troppo generale perché il ? può essere legato a
qualunque tipo, in particolare ad Object che non ha il metodo
disegna.
F. Damiani - Alg. & Lab. 04/05 (da A. Martelli - P.in Rete & L. 04/05)
Il “?” può essere limitato con la notazione
public void disegnaTutto(List<? extends Forma> forme)
{// Body del metodo disegnaTutto }
in cui il tipo degli elementi della lista può essere una qualunque
sottoclasse di Forma, e quindi certamente avrà il metodo
disegna.
F. Damiani - Alg. & Lab. 04/05 (da A. Martelli - P.in Rete & L. 04/05)
AUTO-BOXING
Le strutture come Collection possono contenere solo oggetti.
Quindi per inserire un tipo primitivo (es. int) occorre convertirlo
(boxing) nel corrispondente oggetto (es. Integer). Viceversa,
quando si estrae un oggetto dalla collezione occorre riconvertirlo
nel tipo primitivo (unboxing). Nella versione 1.5 boxing e
unboxing sono fatti automaticamente dal compilatore.
ArrayList<Integer> al = new ArrayList<Integer>();
PRIMA DI Java 1.5
IN Java 1.5
al.add(0, new Integer(25));
int x = (al.get(0)).intValue();
al.add(0, 25);
int x = al.get(0);
F. Damiani - Alg. & Lab. 04/05 (da A. Martelli - P.in Rete & L. 04/05)
ESERCIZI (FACOLTATIVI)
Riscrivere, usando i nuovi costrutti presenti in Java 1.5, il
codice relativo ai seguenti esercizi svolti in laboratorio:
•E6
•E7
•E8
•E9
•E12
F. Damiani - Alg. & Lab. 04/05
Scarica