Advanced   Java   Services
Generics
Back Next Up Home

generics basics


Das klassische Problem, das zur Einführung von generics geführt hat

ArrayList list = new ArrayList();   //1
list.add("Hello World");            //2
list.add(new Integer("1"));         //3
String hi = (String)list.get(0);    //4
String low = (String)list.get(1);   //5  RuntimeException: ClassCastException

Der cast ist notwendig, da next() den Typ Objekt zurückliefert. Da in eine ArrayList beliebige Objekte aufgenommen werden können, ist kein anderer Rückgabetyp möglich. Obiger Code wird vom Compiler nicht beanstandet, führt aber zur Laufzeit zu einer ClassCastException. Wollte der programmierer nur Strings in die ArrayList aufnehmen, so ist in Zeile 3 ein falsches Element aufgenommen worden. Es gab bisher keine Möglichkeit, das den Compiler prüfen zu lassen. Ab 1.5 kann man nun aber beim Erstellen eines Containers angeben, welcher Elementtyp gespeichert werden soll. Die neue Syntax ermöglicht eine Überprüfung zur Compile-zeit und ist somit wesentlich weniger fehleranfällig als der nachträgliche cast, der damit überflüssig wird.


ArrayList<String> list = new ArrayList<String>();  //1 
list.add("Hello World");           //2
list.add(new Integer("1"));        //3 Error at compiletime: cannot find symbol :
                                   //  method add(java.lang.Integer) 
String hi = list.get(0);           //4 cast überflüssig

Durch die Typangabe in den spitzen Klammern wird eine ArrayList erzeugt, die ausschließlich Strings aufnehmen kann, man nennt sie eine "ArrayList von Strings". Bei allen Methoden der Klasse, die Elemente in die Liste aufnehmen wird vom Compiler der Typ Object durch den Typ String ersetzt. Damit kann der Compiler in Zeile 3 mit der entsprechenden Fehlermeldung reagieren. Die gefürchtete ClasscastException kann nicht mehr auftreten. Der Gewinn ist größer als man zunächst glauben mag. Mit dem nachträglichen notwendige Cast kann dieses eine Statement richtig sein (oder auch nicht...) Durch den Einsatz von ArrayList als generische Klasse wird eine ArrayList von Strings vereinbart. Egal wo man Instanzen dieses generischen Typs im Programm verwendet und wie oft, immer prüft der Compiler, ob die ArrayList als ArrayList von Strings verwendet wird.

War bisher die Signatur der add()-Methode

boolean add(Object ob)

so heißt es jetzt

boolean add(E ob)

wobei E für einen beliebigen Typ steht, der durch den in der aktuellen Vereinbarung erklärten Typ steht.

ArrayList<Integer> intList = new ArrayList<Integer>();

Damit wird intList zu einer "sicheren" Liste. Eine Aufnahme von Objekten anderen Typs ist nicht mehr möglich. Fehler diesbezüglich werden zur Compilezeit erkannt.

Am besten fasst man ArrayList<Type> als eine Art von Typ auf, das hilft für die Konsequenzen, die sich aus der neuen Spracheigenschaft ergeben.

ArrayList<X> ist nicht typverwandt mit ArrayList<Y>


ArrayList<Object>  listOfObjects  = new ArrayList<Object>();  //1
ArrayList<String>  listOfStrings  = new ArrayList<String>();  //2
ArrayList<Number>  listOfNumbers  = new ArrayList<Number>();  //3
ArrayList<Integer> listOfIntegers = new ArrayList<Integer>(); //4

Das folgende kann man erwarten:

// kann alles aufnehmen
listOfObjects.add( new Object() );
listOfObjects.add( "hello" );
listOfObjects.add( new Integer("17") );

// kann nur Strings aufnehmen
listOfStrings.add( "world" );

// kann nur Integers aufnehmen
listOfIntegers.add( new Integer("17") );

// kann Numbers und alle Unterklassen von Numbers aufnehmen
Number num = new Float("16.99")
listOfNumbers.add( num );
listOfNumbers.add( new Integer("17") );
listOfNumbers.add( new Double("3.14") );

top Back Next Up Home