- Generics | Overview
- Generics | Generische Programmierung
- Generics | Generische Klasse
- Generics | Generische Typparameter
- Generics | Generische Interfaces
- Generics | Generische Methoden
- Generics | Generische Felder
- Generics | Generische Collections (ArrayList)
- Generics | Diamond-Operator
- Generics | Generische Arrays
- Generics | Generische Matrix
- Generics | Example
- Example | GenerischePerson
- Example | "Berufsgruppe"
- Example | GenerischerSpeicher
- Example | Demo
JAVA-B1
Klassen
public class
instance
System.out.println()
{@link Klasse}
{@param Klasse}
getClass().getSimpleName()
extends
Objekte
Interfaces
FAQ classes
Erweitern von Klassen mit extends
finale Konstanten
(@see
Finalisierung von Klassen
)
Polymorphismus
Nested Classes
@Override Annotation
innere Klassen
lokale Klassen
anonyme Klassen
Lamda Expressions
FAQ Nested Classes
Klassen im Detail
Overview
return-Statements
return & void
return bei primitiven Typen
return bei Objekten
return-Statements von Methoden mit/ohne return
Rückkehr ohne return
Rückkehr über return
throws Exception
Kopie oder Referenz
Covariant Return Types
this
this mit Objekt-Feldern
this mit Methoden und im Konstuktor
Zugriffsmodifikatoren
public protected private
Class Member
static
public static final PI
Initialisierung
Initialisierung von Feldern
Initialisierung von Klassenfeldern
Static Block
Lambda-Expressions
Methoden-Referenzen
Enumerationen und enum-Types
Enumerationskonstanten
Enumerationen mit Werten
Samstag/Sonnabend Example @!
Enumerationen FAQ
Enum @!Descr/Exmpl/Index
Interfaces
Einfache Interfaces (Marker)
Interfaces mit Methoden
Default-Methoden
static
Interfaces FAQ
Vererbung / Inheritance
Vererbung / Inheritance
super Keyword
method-overriding-and-hiding
hiding-of-fields
object-as-superclass
Finalisierung
Finale Klassen und Methoden
Finale Methoden
Finale Utility-Klasse "IdGenerator"
"Template-Methode"-Pattern
DataProcessor process(){ r(), p(), w() }
Composition-over-Inheritance
abstract
Abstrakte Klassen und Methoden
Beispiel
Abstrakte Klassen und Methoden
abstract
Implementierungsklassen
FAQ Vererbung
Kein this in super(..)
Verhindern Überschreiben von Membern
Generics
Generische Programmierung
Generische Typparameter
Generische Klassen
Generische Interfaces
Generische Methoden
Generische Felder
Generische Collection (ArrayList)
Diamond Operator
Generische Arrays
Example
Beispiel "GenerischerSpeicher"
Ring-Speicher-Algorithus mit generischem Array
Beispiel: GenerischePerson mit Berufsgruppe
Beispiel: Berufsgruppe mit Static/Non-Static Nested Classes
Modularisierung
Package
Overview
Package Structure
Package Info
Modules
Overview
Setup
Setup
Module Info
Java New Features Java 8+
Java Record
Record Syntax
Record Demo
Herkömmliche POJOs
Lösung mit Records
Records Zusammenfassung
INDEX
Overview
Generics | Overview
Die Generische Programmierung ist ein Verfahren bei welchem man mit Hilfe von Typ-Parametern sowohl Klassen als auch Methoden, Felder und damit auch Interfaces und vieles andere mehr generalisieren kann. Die Typen von Variablen, Parametern oder auch return-Typen werden hierbei erst zum Zeitpunkt der Instanzierung definiert.
Generische Programmierung und ein Verständnis von generischen Typparametern bildet die Grundlage für ein Verständnis der Nutzung von Java Collections. Alle Collections der Java Collection API sind generische.
Generische Programmierung
Generics | Generische Programmierung
Es gibt generische Klassen, generische Interfaces, generische Methoden, generische Felder, generische Collections sowie auch Arrays und generische Collections wiederum von generischen Collections. Wir geben einen Einblick wie generische Programmierung zu verstehen ist und wie die zugehörige Syntax hierzu aussieht.
Generische Klasse
Generics | Generische Klasse & Typparameter
Generische Klassen sind normale Klasse mit dem kleinen aber bedeutsamen Unterschied, dass Sie einen zusätzlichen Parameter haben: Den Typ-Parameter.
Der Type-Parameter, dt. Typparameter, ist ein Parameter mit welchem Klassen, Methoden und Felder ergänzt werden können, um einen Datentyp erst später zum Zeitpunkt der Erzeugung einer Instanz definieren zu müssen bzw. dieser ergibt sich letztendlich dann als Wert automatisch.
Eine Klasse, welche 1 bis n Typ-Parameter deklariert.
Der Typparameter wird an den Namen der Klasse angehängt. Falls es mehrere sind, werden diese über ein Komma getrennt.
public class Box<T> {
private T wert;
public void set(T wert) { this.wert = wert; }
public T get() { return wert; }
}
Ab diesem Punkt kann der Datentyp für T genauso
im Programmcode verwendet werden wie sonst String, Object und andere Klassen auch.
Typparameter angeben
Basierend auf dem Typ-Parameter ist es damit möglich, sich das Programmieren von BoxString, BoxSchuh als Schuhschrank, BoxFahrzeug als Garage und dergleichen zu ersparen, weil man schlichtweg den Typparameter wie String, Schuh, Fahrzeug angeben kann.
public static void main(String[]args) {
Box<Schuh> schuhschrank = new Box<Schuh>();
Box<Fahrzeug> garage = new Box<Fahrzeug>();
Bod<Flugzeug> hangar = new Box<Flugzeug>();
Box<String> textBox = new Box<>();
textBox.set("Hallo");
String s = textBox.get();
}
Typparameter sind für Klassen
Der Typparamter wird angehängt an dne Klassennamen.
Ab diesem Punkt kann der Datentyp für T genauso
im Programmcode verwendet werden wie sonst String, Object und andere Klassen auch.
Für int- oder double-Werte sind allerings die Wrapper-Klassen wie Integer(Wrapper-Klasse) oder Double zu verwenden.
public class Box<T> {
private T wert;
public void set(T wert) { this.wert = wert; }
public T get() { return wert; }
}
Generische Interfaces
Generics | Generische Interfaces
Generische Interfaces werden sinngemäß ähnlich deklariert wie Interfaces und wie generische Klassen: Man hängt Typparameter an und nutzt diese.
Ein Interface mit Typparameter(n), das Implementierungen flexibel macht.
Jeder weiß, was ein typisches Key-Value-Pair oder Schlüssel-Wert-Paar ist. Das Prinzip ist immer das selbe, aber mit einem generischen Interfaces können wir die Methoden getKey und ketValue zentral vorgeben, auch wenn sich der Typ des Schlüssels oder des Wertes ändern darf.
public interface Pair<K, V> {
K getKey();
V getValue();
}
Merke: Auch default-Methoden und static-Blöcke sind möglich.
Methoden implementieren und Typparameter übernehmen
Wenn das Interfaces noch K und V fordert: Diese Typen übernimmt man so wie die sind.
public class SimplePair<K, V> implements Pair<K, V> {
private final K key;
private final V value;
/** Konstruktor */
public SimplePair(K key, V value) { this.key = key; this.value = value; }
public K getKey() { return key; }
public V getValue() { return value; }
}
Generische Methoden
Generics | Generische Methoden
Generische Interfaces werden sinngemäß ähnlich deklariert wie Interfaces und wie generische Klassen: Man hängt Typparameter an und nutzt diese.
Typparameter bei Parameter verwenden und zusätzlich angeben.
Sofern der Typ-Parameter U nicht bereits über die Klasse
wie beispielsweise class Util<U> definiert
wurde, besteht bei der Deklaration der Methode das Problem darin, dass der Compiler
und die Runtime keine Ahnung haben, auf welchen Typ nun U
hier eigentlich verweist.
public static <U> void printArray(U[] array){ ... }
stellt sicher, dass U als Typ-Parameter erkannt wurde.
public class Util {
public static <U> void printArray(U[] array) {
for (U elem : array) {
System.out.println(elem);
}
}
}
Merke: Typ-Parameter verweisen auf Klassen, Interfaces etc.
Ein typisierter Parameter lässt den Typ erkennen.
Beim Aufruf muss der generische Typparameter nicht zusätzlich übergeben werden. Der Typparameter, welcher in der Methode U lautet, ergibt sich aus dem Datentyp des übergebenen Wertes automatisch.
Integer[] nums = {1,2,3};
Util.printArray(nums);
Generische Felder
Generics | Generische Felder
Generische Felder
Typparameter bei Parameter verwenden und zusätzlich angeben.
In diesem Beispiel erkennt das Feld value seinen Datentyp über den an den Klassennamen angehängten Typparameter.
public class ValueHolder<T> {
private T value; // Generisches Feld
public ValueHolder(T v) { value = v; } // Konstruktor
public T get() { return value; } // Getter
}
Merke: Typ-Parameter verweisen auf Klassen, Interfaces etc.
Generische Collections
Generics | Generische Collections (ArrayList)
Die meisten Entwickler arbeiten üblicherweise mit den zig Klassen und zig Interfaces aus dem Java-Collection-Framework. Alle diese Core-Collection-Interfaces und deren Implementierungsklassen sind generisch mit 1 bis 2 Typ-Parametern.
Das Java Collection Frameworks ist thematisch so umfangreich dass wir dafür einen völlig eigenen Themenblock für die Grundlagen und weitere völlig eigene Themenblöcke für vertiefende Aspekte geschaffen haben.
Die Nutzung ist aber vergleichbar einfach.
Eine ArrayList implementiert das List<T> Interface
Die ArrayList ist eine der mit Abstand am häufigsten eingesetzten Collection-Klassen. Das gilt auch über die Nutzung von Instanzen mit der Speicherung als List.
// Ohne Diamond-Operator
List<String> liste01 = new ArrayList<String>();
liste01.add("A");
String e01 = liste01.get(0);
// Mit Diamond-Operator
List<String> liste02 = new ArrayList<>();
liste02.add("A");
String e02 = liste02.get(0);
Der Diamond-Operator <>]> beschafft sich einen Typ beim Kompilieren automatisch von der linken Seite der Wertzuweisung: Der Typ der Variable gibt den vollständigen Typ an.
Diamond-Operator
Generics | Diamond-Operator
Der Diamond-Operator ist eine Kurzfassung bei der Erzeugung von Instanzen, wenn die Deklaration und Initialisierung in der selben Zeile realisiert wird.
// Ohne Diamond-Operator
List<String> liste01 = new ArrayList<String>();
liste01.add("A");
String e01 = liste01.get(0);
// Mit Diamond-Operator
List<String> liste02 = new ArrayList<>();
liste02.add("A");
String e02 = liste02.get(0);
// Ohne Diamond-Operator
List<String> liste01 = new ArrayList<String>();
liste01.add("A");
String e01 = liste01.get(0);
// Mit Diamond-Operator
List<String> liste02 = new ArrayList<>();
liste02.add("A");
String e02 = liste02.get(0);
// Ohne Diamond-Operator
List<String> liste01 = new ArrayList<String>();
liste01.add("A");
String e01 = liste01.get(0);
// Mit Diamond-Operator
List<String> liste02 = new ArrayList<>();
liste02.add("A");
String e02 = liste02.get(0);
// Ohne Diamond-Operator {#1}
List<String> liste01 = new ArrayList<String>();
liste01.add("A");
String e01 = liste01.get(0);
// Mit Diamond-Operator {#2}
List<String> liste02 = new ArrayList<>();
liste02.add("A");
String e02 = liste02.get(0);
/** UDS 1.5.3.89 CodeHelper */
// {#1} Initialisiere die Queue
GenerischeWarteschlange<String> q = new GenerischeWarteschlange<>(5);
// {#2} Enqueue-Test
q.enqueue("A");
Generische Arrays
Generics | DGenerische Arrays
Der Diamond-Operator ist eine Kurzfassung bei der Erzeugung von Instanzen, wenn die Deklaration und Initialisierung in der selben Zeile realisiert wird.
// Ohne Diamond-Operator
List<String> liste01 = new ArrayList<String>();
liste01.add("A");
String e01 = liste01.get(0);
// Mit Diamond-Operator
List<String> liste02 = new ArrayList<>();
liste02.add("A");
String e02 = liste02.get(0);
Generische Matrix
Generics | Generische Matrix
Bei einer generischen Matrix beinhaltet der Wert einer generischen Collection wiederum Datentypen eines generischen Typs.
So kann die Matrix als Speicherplatz für mehrere String-Listen dienen.
Wir können aber auch eine Map-artige Matrix erzeugen, bei welcher wir Integer-Listen von Zahlen erfassen und diese wiederum über einen String-Key in einer Map speichern.
// === Mit Diamond-Operator (üblich)
List<List<String>> matrix = new ArrayList<>();
matrix.add(new ArrayList<>(List.of("a","b","c")));
Map<String, List<Integer>> map = new HashMap<>();
map.put("zahlen", List.of(1,2,3));
map.put("A", List.of(10,20,30));
map.put("B", List.of(40,50,60));
// === Ohne Diamond-Operator (ursprünglich üblich)
List<List<String>> matrix = new ArrayList<List<String>>();
matrix.add(new ArrayList<>(List.of("a","b","c")));
Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();
map.put("zahlen", List.of(1,2,3));
map.put("A", List.of(10,20,30));
map.put("B", List.of(40,50,60));
Wenn eine generische Klasse einen generischen Typparameter einer generischen Klasse erwartet, so ist es durchaus auch möglich und üblich, dass der referenzierte Datentyp wiederum ein generischer Datentyp ist.
Example
Generics | Example
Das nachfolgende Beispiele beinhalten Klassen, Methoden, Felder mit generischen Typparametern.
Es wird eine Container-Klasse Berufsgruppe als Container für
Static-Nested-Class-Definitionen
wie new Berufsgruppe.Arbeitsloser()
sowie auch Non-Static-Class-Definitionen wie
new new Berufsgruppe().new Astronaut()
verwendet.
Das Beispiel arbeitet mit generischen Arrays und simuliert eine Queue als Ringspeicher.
Es werden KEINE Collections verwendet, obwohl die eigentlich besser geeignet wären
GenerischePerson
Generics | GenerischePerson
Die generische Klasse GenerischePerson
dient im Kern dazu, den Typ einer Person mit einem
zweiten Datentyp wie in diesem Falle einer
Berufsgruppe nicht als normalen
String-Wert sondern als Instanz verknüpfen zu können,
um ein Schlosser-Objekt mit einer Person verknüpfen zu können,
so dass eine Schlosser-Person entsteht.
Wir schränken den Typparameter ein.
GenerischePerson<T extends Berufsgruppe>
package com.stuelken.java.b1.generics.e01.generischerspeicher;
/**
* Eine Klasse zur Erfassung von Personen als Objekten wie beispielsweise einer Astronaut-Person,
* einer Papst-Person.
*
* @author t2m
*
* @param <T>
*/
public class GenerischePerson<T extends Berufsgruppe> {
/**
* Name der Person, über Konstruktor definiert, damit nicht mehr verändert.
*/
private final String name;
/**
* Getter für {@link #name}
*
* @return
*/
public String getName() {
return name;
}
/**
* Referenz auf irgendeinen Beruf; über Konstruktor definiert, danach nicht mehr verändert.
*/
private T beruf;
/**
* Getter für {@link #beruf}
*
* @return
*/
public T getBeruf() {
return beruf;
}
/**
* Konstruktor für eine {@link GenerischePerson} Instanz.
*
* @param name Name der Person wie beispielsweise "Alois".
* @param beruf Der Beruf über eine von {@link Berufsgruppe} abgeleitete Klasse.
*/
public GenerischePerson(String name, T beruf) {
this.name = name;
this.beruf = beruf;
}
/**
* Überschreiben der von {@link Object} geerbten {@link Object#toString()} Methode.
*/
@Override
public String toString() {
return String.format("Person(%s, %s)", name, beruf.getClass().getSimpleName());
}
}
Ausgabe
//@formatter:off
/*
Nichts.
*/
//@formatter:on
Erläuterungen
Berufsgruppe
Generics | "Berufsgruppe"
Die Klasse Berufsgruppe ist eine
Container-Klasse für sowohl
Static-Nested-Class-Definitionen
wie new Berufsgruppe.Arbeitsloser()
sowie auch Non-Static-Class-Definitionen wie
new new Berufsgruppe().new Astronaut().
Typen dieser Klasse werden benötigt für den Typparameter der GenerischePerson-Klasse.
Berufsgruppe
package com.stuelken.java.b1.generics.e01.generischerspeicher;
/**
* Container-Klasse für sowohl Static-Nested-Class-Definitionen wie {@link Arbeitsloser} sowie auch
* Non-Static-Class-Definitionen wie {@link Astronaut}.
*
* @author t2m
*
*/
public class Berufsgruppe {
/*
* === Statische Innere Klassen
*/
/**
* Statische Innere Verschachtelte Klasse (static nested class), erfordert KEIN Objekt von
* {@link Berufsgruppe}, um eine Instanz erzeugen zu können.
*
* @author t2m
*
* {@index "Example/Klassen/NestedClass/StaticNestedClass/Berufsgruppe.Arbeitsloser"}
*
*/
public static class Arbeitsloser extends Berufsgruppe {
public void daumenDrehen() {
System.out.println("Ich drehe meine Daumen. ");
}
}
/*
* === Non-Static-Nested-Class
*
* Diese Klassen können nur über berufsgruppe.new Astronaut() erzeugt werden, nachdem eine Instanz
* Berufsgruppe berufsgruppe = new Berufsgruppe() erzeugt wurde!
*/
/**
*
* * {@index "Example/Klassen/NestedClass/Non-Static-Nested-Class/new
* Berufsgruppe().newArbeitsloser();"}
*
* @author t2m
*/
public class Astronaut extends Berufsgruppe {
public void meldung() {
System.out.println("Houston, mir habbe do a Problemscher.");
}
}
public class Fischer extends Berufsgruppe {
public void fischen() {
System.out.println("Heute beisst keiner an.");
}
}
public class Kraftfahrer extends Berufsgruppe {
public void reparieren() {
System.out.println("Ich repariere das Ding nicht. Das Fahrzeug ist fertig.");
}
}
public class Papst extends Berufsgruppe {
public void beten() {
System.out.println("... murmel, murmel ...");
}
}
public class Programmierer extends Berufsgruppe {
public void tickerTicker() {
System.out.println("Ticker, ticker, ticker. Geht nicht! Ticker, ticker.");
}
}
public class Schlosser extends Berufsgruppe {
public void dingBoing() {
System.out.println("Ding! Boing! Boing! Ding! .... Klong!");
}
}
}
Ausgabe
//@formatter:off
/*
Keine.
*/
//@formatter:on
Erläuterungen
Generischer Speicher
Generics | GenerischerSpeicher
Eine Instanz von GenerischerSpeicher ist in der Lage, über einen Typ-Parameter Personen-Objekte beliebiger Klassen zu erfassen, sofern diese denn eine Berufsgruppe haben.
Das Beispiel bedeutlich zugleich das Prinzip, wie man generische Arrays instanzieren kann.
GenerischeWarteschlange<V>
package com.stuelken.java.b1.generics.e01.generischerspeicher;
/**
* Objekte dieser Klasse beinhalten eine Warteschlange mit einer begrenzten Anzahl von
* maximal-möglichen Speicherplätzen basierend auf einem generischem Array nach dem Prinzip eines
* Ring-Speichers, indem Head- und Tail-Index beim Anhängen von Elementen und Entfernen von
* Elementen jeweils wie auch die Anzahl der tatsächlich gespeicherten Elemente in
* {@link #ringElementeWartend} angepasst.
*
* @author t2m
*
* @param <V> Typparameter für die zu speichernden Objekte
*/
public class GenerischeWarteschlange<V> {
/**
* Array für die zuspeichenden Elemente des generischen Typs "V" welche in der
* {@link GenerischeWarteschlange} warten dürfen.
*
* Hinweis: Java ermöglicht keine direkte Erzeugung eines Arrays vom Typ eines generischen
* Typparameters.
*
* {@code private V[] elemente = (V[]) new Object[kapazitaet]; }
*
*/
private V[] ringElementeWartend;
private int numberOfWaitingElements = 0;
/**
* Index für das erste Element am Kopf {@link #ringHeadIndex} der Schlange; dient zum Lesen und
* entfernen des ersten Wertes.
*/
private int ringHeadIndex = 0;
/**
* Index am Schwanz und damit dem {@link #ringTailNextFreeIndex} der Schlange; dient zum Anhängen
* eines weiteren Elements.
*/
private int ringTailNextFreeIndex = 0;
/**
* Arrays sind in Java fix dimensioniert.
*/
private int ringCapacityMax;
/**
* Konstruktor: Definiert {@link #ringCapacityMax} als maximale
* Speicherkapazität und erzeugt einen generischen
* Array über {@code (V[]) new Object[ringCapacityMax]}.
*
* {@index "Examples/Klassen/GenerischeProgrammierung/GenerischeArrays/GenerischenArrayErzeugen"}
*
* @param ringCapacityMax Anzahl der Elemente im Array
*
* @see SuppressWarnings
*/
@SuppressWarnings("unchecked")
public GenerischeWarteschlange(int ringCapacityMax ) {
// Sicherstellen, dass der Speicher seine Kapazität kennt.
this.ringCapacityMax = ringCapacityMax ;
// WICHTIG: Java erlaubt kein direktes Generics-Array, daher der Cast.
// Compiler-Warnungen hierfür unterdrücken.
this.ringElementeWartend = (V[]) new Object[ringCapacityMax];
}
/**
* Fügt ein Element hinten an (engl: enqueue).
*
* @param elem Neues Element
*/
public void enqueueAtTail(V elem) {
if (isFull()) {
// throw new IllegalStateException("Speicher ist voll!");
System.out.println("Sorry, Warteschlange ist voll. Element wird nicht erfasst. " + elem);
return;
}
this.ringElementeWartend[this.ringTailNextFreeIndex++ % this.ringCapacityMax] = elem;
// Zähler raufzählen.
numberOfWaitingElements++;
System.out.println("Fuegte elem hinzu: " + "\n" + getIndent() + elem + this.stateOfQueue());
}
/**
* Hilfsmethode, gibt Zustand der {@link GenerischeWarteschlange} aus.
*
* @return String mit Info zu {@link #size()}, {@link #ringHeadIndex},
* {@link #enqueueAtTail(Object)}.
*/
public String stateOfQueue() {
return "\n" + getIndent() + "size: " + this.size() + " head:" + this.ringHeadIndex + " tail:"
+ this.ringTailNextFreeIndex + " waiting:" + this.numberOfWaitingElements;
}
public String getIndent() {
return " "; // 8 Leerzeichen
}
/**
* Entfernt ein Element vorne (dequeue)
*/
public V takeFromFront() {
if (this.isEmpty()) {
throw new IllegalStateException("Speicher ist leer!");
}
// Referenz auf Element beschaffen
V firstElement = this.ringElementeWartend[this.ringHeadIndex];
System.out.println("takeFromFront:" //
+ "\n" + getIndent() + "Habe das erste wartende Element entfernt, Schlange noch nicht angepasst. " //
+ "\n" + getIndent() + firstElement + this.stateOfQueue()); //
// Die aktuelle Kopfposition im Array mit null überschreiben.
this.ringElementeWartend[this.ringHeadIndex] = null;
//
this.shiftHead();
// Anzahl anpassen
this.numberOfWaitingElements--;
System.out.println(getIndent() + "Zustand nach entfernten des Elements: " + this.stateOfQueue());
return firstElement;
}
/**
*
*/
private void shiftHead() {
System.out.println("shiftHead: Aktualisiere den Index.");
// Den Index des Kopf der Schlange verschieben, indem der Index erhöht wird.
// Damit ist das nachfolgende Element jetzt das erste Elemente.
this.ringHeadIndex++;
// Falls der head sich an Position der Kapazität befindet, ist der Index zu hoch.
// Über Modulo wird aber
this.ringHeadIndex = this.ringHeadIndex % this.ringCapacityMax;
}
/**
* Wenn der Index des Kopfs dem Ende entspricht, hat die Schlange keinerlei Elemente.
*
* @return
*/
public boolean isEmpty() {
return numberOfWaitingElements == 0;
}
/**
*
* @return Liefert true wenn die aktuelle {@link #size()} der {@link #ringCapacityMax} entspricht.
*/
public boolean isFull() {
return numberOfWaitingElements == this.ringCapacityMax;
}
/**
* Liefert die aktuelle Anzahl der gespeicherten Elemente der {@link GenerischeWarteschlange}
* Schlange.
*
* @return Anzahl als Differenz aus Index des Endes und Index des Kopfes
*/
public int size() {
return this.numberOfWaitingElements;
}
}
Ausgabe
//@formatter:off
/*
Fuegte elem hinzu:
Person(Antonia 1, Arbeitsloser)
size: 1 head:0 tail:1 waiting:1
Fuegte elem hinzu:
Person(Bertram 2, Fischer)
size: 2 head:0 tail:2 waiting:2
Fuegte elem hinzu:
Person(Cecile 3, Schlosser)
size: 3 head:0 tail:3 waiting:3
Fuegte elem hinzu:
Person(Doris 4, Programmierer)
size: 4 head:0 tail:4 waiting:4
Fuegte elem hinzu:
Person(Emilia 5, Programmierer)
size: 5 head:0 tail:5 waiting:5
Fuegte elem hinzu:
Person(Frank 6, Fischer)
size: 6 head:0 tail:6 waiting:6
Fuegte elem hinzu:
Person(Gert 7, Papst)
size: 7 head:0 tail:7 waiting:7
Fuegte elem hinzu:
Person(Hanibal 8, Kraftfahrer)
size: 8 head:0 tail:8 waiting:8
Sorry, Warteschlange ist voll. Element wird nicht erfasst. Person(Ida 8+, Astronaut)
Sorry, Warteschlange ist voll. Element wird nicht erfasst. Person(Ida 8+, Astronaut)
Sorry, Warteschlange ist voll. Element wird nicht erfasst. Person(Ida 8+, Astronaut)
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Antonia 1, Arbeitsloser)
size: 8 head:0 tail:8 waiting:8
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 7 head:1 tail:8 waiting:7
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Bertram 2, Fischer)
size: 7 head:1 tail:8 waiting:7
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 6 head:2 tail:8 waiting:6
Fuegte elem hinzu:
Person(Julius, Papst)
size: 7 head:2 tail:9 waiting:7
Schleife ueber alle Elemente bis leer:
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Cecile 3, Schlosser)
size: 7 head:2 tail:9 waiting:7
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 6 head:3 tail:9 waiting:6
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Doris 4, Programmierer)
size: 6 head:3 tail:9 waiting:6
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 5 head:4 tail:9 waiting:5
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Emilia 5, Programmierer)
size: 5 head:4 tail:9 waiting:5
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 4 head:5 tail:9 waiting:4
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Frank 6, Fischer)
size: 4 head:5 tail:9 waiting:4
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 3 head:6 tail:9 waiting:3
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Gert 7, Papst)
size: 3 head:6 tail:9 waiting:3
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 2 head:7 tail:9 waiting:2
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Hanibal 8, Kraftfahrer)
size: 2 head:7 tail:9 waiting:2
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 1 head:0 tail:9 waiting:1
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Julius, Papst)
size: 1 head:0 tail:9 waiting:1
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 0 head:1 tail:9 waiting:0
*/
//@formatter:on
Erläuterungen
Beispiel
Example | Beispiel
Es gibt generische Klassen, generische Interfaces, generische Methoden, generische Felder, generische Collections sowie auch Arrays und generische Collections wiederum von generischen Collections. Wir geben einen Einblick wie generische Programmierung zu verstehen ist und wie die zugehörige Syntax hierzu aussieht.
package com.stuelken.java.b1.generics.e01.generischerspeicher;
import com.stuelken.java.b1.generics.e01.generischerspeicher.Berufsgruppe.*;
/**
* Demo für {@link GenerischeWarteschlange}, simuliert einen FIFO-Prozess bei welchem Elemente einer
* Wartschlange am Ende hinzugefügt werden und am Beginn entnommen werden, wenn man quasi dran ist.
*
* @author t2m
*/
public class GenerischeDemo_Personen {
/**
* Hauptprogramm; simuliert folgenden FIFO-Prozess:
*
* <ol>
* <li>Erzeugt eine Warteschlange für {@link GenerischePerson} Objekte.</li>
* <li>Erzeugt die zugehörige Instnz für die {@link GenerischeWarteschlange}</li>.
* <li>Fügt {@link GenerischePerson} Objekte hinzu.</li>
* <li>Fehlschlag eines Versuchs, eine Person über die Kapazität hinaus hinzuzufügen.</li>
* <li>Entnimmt zwei Personen nach FirstInFirstOut-Prinzip, so dass wieder 1 Feld frei ist.</li>
* <li>
* </ol>
*
* @param args Keine Argumente
*/
public static void main(String[] args) {
// (1)
GenerischeWarteschlange<GenerischePerson<? extends Berufsgruppe>> personenQueue;
// (2)
personenQueue = new GenerischeWarteschlange<>(8);
Berufsgruppe berufsgruppe = new Berufsgruppe();
// (3)
// Instanzierung eines Objekts einer Static-Nested-Class
personenQueue.enqueueAtTail(new GenerischePerson<Arbeitsloser>("Antonia 1", new Berufsgruppe.Arbeitsloser()));
// Instanzierung von Objekten von Non-Static-Nested-Classes
personenQueue.enqueueAtTail(new GenerischePerson<Fischer>("Bertram 2", berufsgruppe.new Fischer()));
personenQueue.enqueueAtTail(new GenerischePerson<Schlosser>("Cecile 3", berufsgruppe.new Schlosser()));
personenQueue.enqueueAtTail(new GenerischePerson<Programmierer>("Doris 4", berufsgruppe.new Programmierer()));
personenQueue.enqueueAtTail(new GenerischePerson<Programmierer>("Emilia 5", berufsgruppe.new Programmierer()));
personenQueue.enqueueAtTail(new GenerischePerson<Fischer>("Frank 6", berufsgruppe.new Fischer())); //
personenQueue.enqueueAtTail(new GenerischePerson<Papst>("Gert 7", berufsgruppe.new Papst()));
personenQueue.enqueueAtTail(new GenerischePerson<Kraftfahrer>("Hanibal 8", berufsgruppe.new Kraftfahrer()));
// (4) Fehlschlagend: Zu viele Elemente.
personenQueue.enqueueAtTail(new GenerischePerson<Astronaut>("Ida 8+", berufsgruppe.new Astronaut()));
personenQueue.enqueueAtTail(new GenerischePerson<Astronaut>("Ida 8+", berufsgruppe.new Astronaut()));
personenQueue.enqueueAtTail(new GenerischePerson<Astronaut>("Ida 8+", berufsgruppe.new Astronaut()));
// (5) Zwei entfernen
GenerischePerson entfernt1 = personenQueue.takeFromFront();
GenerischePerson entfernt2 = personenQueue.takeFromFront();
personenQueue.enqueueAtTail(new GenerischePerson<Papst>("Julius", berufsgruppe.new Papst()));
// (4) Anhängen
System.out.println("Schleife ueber alle Elemente bis leer:");
while (!personenQueue.isEmpty()) {
GenerischePerson p;
p = personenQueue.takeFromFront();
}
}
}
//@formatter:off
/*
Fuegte elem hinzu:
Person(Antonia 1, Arbeitsloser)
size: 1 head:0 tail:1 waiting:1
Fuegte elem hinzu:
Person(Bertram 2, Fischer)
size: 2 head:0 tail:2 waiting:2
Fuegte elem hinzu:
Person(Cecile 3, Schlosser)
size: 3 head:0 tail:3 waiting:3
Fuegte elem hinzu:
Person(Doris 4, Programmierer)
size: 4 head:0 tail:4 waiting:4
Fuegte elem hinzu:
Person(Emilia 5, Programmierer)
size: 5 head:0 tail:5 waiting:5
Fuegte elem hinzu:
Person(Frank 6, Fischer)
size: 6 head:0 tail:6 waiting:6
Fuegte elem hinzu:
Person(Gert 7, Papst)
size: 7 head:0 tail:7 waiting:7
Fuegte elem hinzu:
Person(Hanibal 8, Kraftfahrer)
size: 8 head:0 tail:8 waiting:8
Sorry, Warteschlange ist voll. Element wird nicht erfasst. Person(Ida 8+, Astronaut)
Sorry, Warteschlange ist voll. Element wird nicht erfasst. Person(Ida 8+, Astronaut)
Sorry, Warteschlange ist voll. Element wird nicht erfasst. Person(Ida 8+, Astronaut)
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Antonia 1, Arbeitsloser)
size: 8 head:0 tail:8 waiting:8
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 7 head:1 tail:8 waiting:7
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Bertram 2, Fischer)
size: 7 head:1 tail:8 waiting:7
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 6 head:2 tail:8 waiting:6
Fuegte elem hinzu:
Person(Julius, Papst)
size: 7 head:2 tail:9 waiting:7
Schleife ueber alle Elemente bis leer:
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Cecile 3, Schlosser)
size: 7 head:2 tail:9 waiting:7
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 6 head:3 tail:9 waiting:6
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Doris 4, Programmierer)
size: 6 head:3 tail:9 waiting:6
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 5 head:4 tail:9 waiting:5
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Emilia 5, Programmierer)
size: 5 head:4 tail:9 waiting:5
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 4 head:5 tail:9 waiting:4
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Frank 6, Fischer)
size: 4 head:5 tail:9 waiting:4
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 3 head:6 tail:9 waiting:3
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Gert 7, Papst)
size: 3 head:6 tail:9 waiting:3
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 2 head:7 tail:9 waiting:2
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Hanibal 8, Kraftfahrer)
size: 2 head:7 tail:9 waiting:2
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 1 head:0 tail:9 waiting:1
takeFromFront:
Habe das erste wartende Element entfernt, Schlange noch nicht angepasst.
Person(Julius, Papst)
size: 1 head:0 tail:9 waiting:1
shiftHead: Aktualisiere den Index.
Zustand nach entfernten des Elements:
size: 0 head:1 tail:9 waiting:0
*/
//@formatter:on
Nicht schön. Aber es funktioniert.
FootNotes, Keywords, Tags
Hinweise, Rechte, Marken
UIO3 Es ist einfacher als Du denkst.
Stelle noch heute Deine Anfrage.
