Generische Klassen (Generics) - Mobile und Verteilte Systeme

Werbung
Javakurs für Anfänger
Einheit 14: Generics
Lorenz Schauer
Lehrstuhl für Mobile und Verteilte Systeme
Heutige Agenda
Generische Klassen (Generics)
 Motivation
 Java Typ-Prüfung
 Warum also Generics?
 Generische Typen selbst definieren
 Generische Typen anwenden
Zusammenfassung
Ausblick
Praxis:
 Generische Klasse BlackBox
schreiben
Lernziele
 Einführung in generische Klassen
 Das Konzept von Generics kennenlernen und verstehen
 Generische Typen schreiben und v.a. benutzen können
04.02.2016
Javakurs 14: Generics - Lorenz Schauer
2
Motivation
Generische Typen (Generics):
 Sind ein syntaktisches Mittel für die generische Programmierung
 Zählen zu den komplexesten Typen in Java
 Seit Java 1.5 fester Bestandteil
 Grundidee: Einführung von Variablen, die Typen (statt wie bisher Werte)
speichern
 Diese Typ-Variablen repräsentieren zum Zeitpunkt der Implementierung unbekannte
Typen.
 Erst bei der Verwendung der Klassen, Schnittstellen und Methoden werden diese
Typ-Variablen durch konkrete Typen ersetzt.
 Damit kann typsichere Programmierung gewährleistet werden.
 Ein bekanntes Beispiel (hatten wir schon):
 Java.util.ArrayList<E>
 Anwendung:
ArrayList<String> meine_liste1 = new ArrayList<String>();
ArrayList<Integer> meine_liste2 = new ArrayList<Integer>();
04.02.2016
Javakurs 14: Generics - Lorenz Schauer
3
Java Typ-Prüfung
Die Typ-Prüfung passiert 2 Mal:
 Durch den Compiler (statisch)
 Führt erste Typ-Prüfung durch.
 Ist weniger „exakt“ als die dynamische Prüfung
 Durch die Laufzeitumgebung JVM (dynamisch)
 Hat absolute Typ-Intelligenz
 Prüft zur Laufzeit (als letzte Instanz), ob der Typ zum zugewiesenen Objekt passt
 Falls nicht, folgt Exception
// Beispiel:
Object o = Integer.valueOf(10);
String s = (String) o;
System.out.println(o);
Anweisungen sind für den Compiler
zunächst völlig in Ordnung.
Statische Typprüfung: korrekt
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer
cannot be cast to java.lang.String
Aber die JVM kann diese Anweisungen nicht
at Test.main(Test.java:8)
ausführen => ClassCastException
Dynamische Typprüfung: falsch!
04.02.2016
Javakurs 14: Generics - Lorenz Schauer
4
Warum also Generics?
Einführung von Generics:
 Compiler bekommt mehr Informationen über die Typen
 So sollen bspw. ClassCastExceptions vermeiden werden.
 Beispiel bei ArrayList:
Ohne parametrisierte Typen
Mit parametrisierten Typen
public static void main(String[] args) {
ArrayList myList = new ArrayList();
myList.add("Hallo");
myList.add(new Hund("Bello","Haski",98));
myList.add(new Hund("Flippo","Schaefer",101));
myList.add("Bello");
for(int i=0; i<myList.size();i++){
Hund h = (Hund) myList.get(i);
System.out.println(h.getName());
}
}
Exception in thread "main"
java.lang.ClassCastException:
java.lang.String cannot be cast to Hund
at Test.main(Test.java:15)
04.02.2016
Compiler-Fehler, da statische Typ-Prüfung
jetzt fehlschlägt!
Javakurs 14: Generics - Lorenz Schauer
5
Generische Typen deklarierten
Man kann eigene generische Typen (Klassen) definieren:
 public class MeineKlasse<T>
 Objekterzeugung dann:
MeineKlasse<Typ> objektname = new MeineKlasse<Typ>();
 Bsp mit String:
MeineKlasse<String> k1 = new MeineKlasse<String>();
 Seit Java7 auch:
MeineKlasse<String> k1 = new MeineKlasse<>();
 Das T steht für den generischen Typen und kann nun als Typ-Variable in der Klasse
benutzt werden:
 Als Instanzvariable:
 Bsp.: private T meine_instanzvariable;
 Als Parameter:
 Bsp.: public MeineKlasse(T value){…}
 Als Rückgabetyp:
 Bsp.: public T doSomeStuff(){…}
Hinweis: Laut Konvention schreibt man T für Typen und E für Elemente
 Muss aber nicht sein, man kann auch <BlaDiBlub> verwenden
04.02.2016
Javakurs 14: Generics - Lorenz Schauer
6
Allgemeines Beispiel
public class MeineKlasse<T> {
Generische Klasse
Mit Typ-Variable T
// Instanzvariablen
private T instanzvariable1;
private T instanzvariable2;
private String name;
private int alter;
Generische
(parametrisierte)
Instanzvariablen
// Konstruktoren
public MeineKlasse(){
this.name = "DefaultName";
this.alter = 0;
}
public MeineKlasse(T value1, T value2){
this.instanzvariable1=value1;
this.instanzvariable1=value2;
}
public MeineKlasse(T value1, T value2, String name, int alter){
this.instanzvariable1=value1;
this.instanzvariable1=value2;
this.name = "DefaultName";
this.alter = 0;
}
//Getter and Setter
public T getInstanzvariable1() {
return instanzvariable1;
}
public void setInstanzvariable1(T instanzvariable1) {
this.instanzvariable1 = instanzvariable1;
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
}
04.02.2016
Javakurs 14: Generics - Lorenz Schauer
Nicht generische
Instanzvariablen
Konstruktor erwartet
die generischen Typen
Konstruktor erwartet
generische und nicht
generische Typen
Methode liefert
generischen Typ
zurück
Methode erwartet
generischen Typ
7
Wie wird die Klasse nun benutzt?
Ein Objekt der generischen Klasse kann nun beim Erzeugen angeben, welchen Typ
es in die Typ-Variable einsetzt.
 Analog zur ArrayList
 ArrayList<String> meineListe = new ArrayList<String>();
 ArrayList meineGenerelleListe = new ArrayList();
 Wird kein Typ angegeben wird implizit die Super-Klasse Object eingesetzt
 D.h.: Dann weiß der Compiler genauso wenig über die „echten“ Typen wie zuvor und
man muss auf Typ-Casting zurückgreifen!
 Das ist nicht der Sinn von Generics und wird mit einer Compiler-Warnung bestraft:
“ArrayList is a raw type. References to generic type ArrayList<E> should be
parameterized“
04.02.2016
Javakurs 14: Generics - Lorenz Schauer
8
Wie wird die Klasse nun benutzt?
public class Test{
objekt1 legt keinen generischen
Typ fest.
=> Es wird implizit Object
verwendet
public static void main(String[] args) {
// Objekt erzeugen:
MeineKlasse objekt1 = new MeineKlasse();
MeineKlasse<String> objekt2=new MeineKlasse<>();
objekt2 setzt String
MeineKlasse<Integer> objekt3=new MeineKlasse<>(); objekt3 setzt Integer
objekt1 setzt Instanzvariable1
// Methoden-Aufrufe
auf „Peter“.
objekt1.setInstanzvariable1("Peter");
String s1 =(String)objekt1.getInstanzvariable1(); Korrekt, da generischer Typ =
Object
objekt2.setInstanzvariable1("Maria");
Bei Nutzung Typ-Cast nötig!
String s2 = objekt2.getInstanzvariable1();
objekt3.setInstanzvariable1(23);
int s3 = objekt3.getInstanzvariable1();
}
}
04.02.2016
objekt2 setzt Instanzvariable1 auf
„Maria“
Korrekt, da generischer Typ = String
objekt3 setzt Instanzvariable1 auf 23
Korrekt, da generischer Typ = int
Javakurs 14: Generics - Lorenz Schauer
9
Programmieraufgabe zu Generics
Schreiben Sie in Analogie zur ArrayList eine generische Klasse BlackBox<E> welche folgende
Methoden anbieten soll:
 add(E element) fügt ein Element Ihrer Box hinzu
 remove(E element) löscht ein Element aus Ihrer Box
 clear() löscht alle Element aus Ihrer Box
 getElementAtPosition(int i) liefert das Element an der Position i zurück
 printNamesOfElements() gibt die Namen sämtlicher Elemente in der BlackBox auf der
Konsole aus
 Hinweis: Nutzen Sie hierfür die Methode toString(), welche von der Oberklasse Object
bereitgestellt wird.
Zusätzlich soll die Klasse folgende Attribute bereitstellen
 String name (welcher über den Konstruktor gesetzt wird)
 Eine geeignete Datenstruktur zum Speichern der Elemente
 Hinweis: Der Einfachheit halber nutzen Sie hier die ArrayList<E>, mit der Sie oben genannte
Methoden leicht implementieren können.
Nutzen Sie nun Ihre neue Klasse BlackBox und erzeugen Sie 2 Instanzen mit unterschiedlichen
Typen.
 Sie können auf Klassen von vorangegangenen Stunden zurückgreifen (Hund, Auto)
Erzeugen Sie nun mehrere Objekte der beiden gewählten Klassen und fügen Sie diese in die
entsprechene BlackBox ein.
Was erscheint auf der Konsole, wenn Sie die printNamesOfElements() Methode auf den
beiden BlackBox Obejekten aufrufen?
04.02.2016
Javakurs 14: Generics - Lorenz Schauer
10
Zusammenfassung
Sie haben nun die grundlegenden Elemente der objektorientierten
Programmiersprache Java kennengelernt:
 Klassen, Objekte, Variablen & Methoden
 Zusammenspiel verschiedener Klassen und Objekte
 Abstraktion und Datenkapselung
 Kontrollstrukturen
 Statische und dynamische Arrays
 Vererbung
 Subtyping, Typ-Casting, …
 Abstrakte Klassen
 Interfaces
 Anonyme innere Klassen





Polymorphismus
Exceptions
Generics
UML
Java API Dokumentation
04.02.2016
Javakurs 14: Generics - Lorenz Schauer
11
Und jetzt…?
Fortführende Themen wären:
 Weitere Datenstrukturen
 (verkettete) Listen, Stack, Schlangen (Queues), Hash-Tables, Bäume (Trees)
 Frameworks
 Collection-Framework
 Nebenläufigkeit
 Threads, Conditions, Synchronisation, Monitore
 GUI-Programmierung mit Swing / JavaFX
 Design-Pattern
 Algorithmen
 Sortieren & Suchen, Rekursion, …
 U.v.m.
=> Einfach am Ball bleiben und viel programmieren ;)
04.02.2016
Javakurs 14: Generics - Lorenz Schauer
12
Vielen Dank!
Vielen Dank
fürs Zuhören und Mitmachen!
04.02.2016
Javakurs 14: Generics - Lorenz Schauer
13
Herunterladen