Controllo dei tipi con array

I dati di una collezione sono normalmente omogenei, cioè hanno lo stesso tipo. Se usiamo gli array, possiamo dichiararne il tipo:
 
int [] arr1 = new int [5]; 
   // arr1 puo' contenere solo int;
BankAccount [] arr2
   // conterra' istanze di BankAccount o
   // di classi derivate;
Comparable [] arr3
   // conterra' istanze di classi che 
   // implementano l'interfaccia Comparable;
Object [] arr4
   // conterra' istanze di una qualunque classe Java

Il compilatore può controllare la consistenza dei tipi:
 

arr1[1] = 3.0; 
   // NO: double in array di int
arr3[0] = new Object( ); 
   // NO: Object non implementa Comparable
arr4[0].compareTo(arr3[0]);
   // NO: metodo compareTo non definito in Object



Tipo di elementi di un Vector

E con i Vector? Gli elementi di un Vector [locale, Medialab, Sun] sono istanze di Object:
 
   // Due metodi di Vector:
Object elementAt(int index) 
   // restituisce l'oggetto alla
   // posizione index
boolean add (Object o) 
   // inserisce o in fondo al vettore

Quindi:

  • Non c'è controllo dei tipi da parte del compilatore;
  • Non si possono mettere dati di tipi elementari in un Vector.
Tutte le strutture dati (collezioni) che vedremo avranno elementi di tipo Object, come Vector.



Controllo dei tipi a run time

Come si può garantire che una collezione (p.e. un Vector) contenga sempre dati dello stesso tipo?
... controllando il tipo di un dato prima di inserirlo, ovviamente....


Esempio: vettore di String: UseStringVector.java
 

import java.util.Vector;

public class UseStringVector{
    public static void main (String [] args){
// dichiariamo un vector per contenere stringhe
        Vector vect = new Vector();
        for (int i=0; i < 10; i++){
            vect.add(""+i);  // inseriamo alcune stringhe
        }
        vect.add(new Object());  // vorremmo vietare questo!!
        for (int i=0; i < vect.size(); i++){
            System.out.println(vect.elementAt(i));
        }
    }
}




Controllo dei tipi in sottoclasse

Soluzione: Definisci una sottoclasse StringVector di Vector, inserendo un controllo sul tipo dei dati inseriti nel vettore [UseStringVector2.java]:
 
public class StringVector extends java.util.Vector{
    public StringVector(){
        super();
    }
    // altri costruttori
    public boolean add (Object element){
    if (element instanceof String)
    return super.add(element);
        else throw new IllegalArgumentException();
    }
    // altri metodi
}

 



Lettura da Vector e cast

Attenzione: i dati che si estraggono da un Vector sono sempre istanze di Object: bisogna usare un cast per manipolarli.
 
String obj1 = (String) vect.elementAt(0);

    // OK: String implements Comparable !!

if (obj1.compareTo(vect.elementAt(1)) <= 0)

    System.out.println("I primi due elementi sono ordinati");

Non si può ridefinire il metodo elementAt in modo da restituire un oggetto di tipo String:
 

public class StringVector extends java.util.Vector{
    ...
    public String elementAt(int index){
       return (String) super.elementAt(index);
    } // provoca errore di compilazione
    ...
}

 



Collezioni di dati elementari

Elementi di tipi elementari Java (int, double, char, boolean, ...) non possono essere inseriti direttamente in collezioni come Vector, perché non sono istanze di Object

Classi contenitore (wrapper):

Integer, Double, Character, Boolean, ...
Servono per racchiudere un dato elementare in un oggetto:
 
...
Integer xnew Integer(5);
...
int y =  x.intValue();
...

Forniscono metodi per convertire dati elementari tra diversi formati, e metodi di utilità generale: si veda ad esempio Integer [locale, Medialab, Sun].
 




Inserimento e lettura di dati elementari

Come si gestisce un vettore di interi?
 
...
// inserimento di un elemento
vect.add(new Integer(num));
...
// estrazione di un elemento
int y =  ((Integer) vect.elementAt(index)).intValue( );
...