JAVA & Objektorientiertes Programmieren 2

Erweiterung der ersten Kartei

Erweiterung der ersten Kartei


Set of flashcards Details

Flashcards 203
Language Deutsch
Category Computer Science
Level University
Created / Updated 19.01.2017 / 09.01.2024
Weblink
https://card2brain.ch/box/20170119_java_objektorientiertes_programmieren_2
Embed
<iframe src="https://card2brain.ch/box/20170119_java_objektorientiertes_programmieren_2/embed" width="780" height="150" scrolling="no" frameborder="0"></iframe>

Welche Implementationen der List<E> gibt es?

ArrayList, LinkedList, Stack*, Vector* etc

*Hinweis: Sehr alte Klassen, bessere Alternativen vorhanden

Zeige eine Implementation einer ArrayList<Temperatur>

(siehe Bild)

Hinweis: Für add() reicht der Typ Collection, erst für set() und get() benötigt man den Typ List (zweifacher cast hier exemplarisch. Nicht elegant!)

Wie ist das Interface Queue aufgebaut?

Spezialisiert die Semantik der Collection zu einer Schlange: Meistens nach FIFO-Semantik (first in, first out), kann aber auch priorisiert sein

Typische Methoden:
offer() - Hängt ein Element am Ende an
- poll() - Entnimmt ein Element am Anfang

(siehe Bild)

Was sind Eigenschaften einer Queue<E>?

Definiert eine Queue von Elementen vom Typ E
- Queue kann eine statische, beschränkte Grösse haben
- Elemente werden am Schwanz (tail) angehängt
- Elemente werden am Kopf (head) entnommen

Was ist der typische Verwendungszweck von einer Queue<E>?

Zwischenspeichern von Objekten vor der Verarbeitung
Beispiele: Warteschlange, Buffer, Unix-Pipe, Druckerqueue

Semantik meist nach FIFO-Prinzip

Welche Arten von Implementationen gibt es für die Queue<E>?

ArrayDeque, DelayQueue, LinkedBlockingQueue, PriorityQueue etc.

Zeige ein Beispiel einer ArrayBlockingQueue<Temperatur>

(siehe Bild)

Beispiel der ArrayBlockingQueue-Implementation:
offer() blockiert (wartet) wenn voll, poll() wenn leer

Wie ist die Deque<E> aufgebaut?

Spezialisiert die Semantik der Collection zu einer Queue welche in beide Richtungen verwendet werden kann

Das ermöglicht u.a. auch einen Stack: FILO-Semantik (first in, last out), was einen klassischen "Stapelspeicher" repräsentiert.

push() - Element auf Stack legen
pop() - Element von Stack abheben

(siehe Bild)

Was sind Eigenschaften einer Deque<E>?

Definiert eine Deque (double ended queue) von Elementen vom Typ E
- Eine Queue welche in beide Richtungen arbeiten kann

Semantik somit wahlweise nach FIFO- oder FILO-Prinzip (abhängig von konkreter Verwendung)

Was ist der typische Verwendungszweick einer Deque<E>?

Zwischenspeichern von Objekten vor/für die Verarbeitung, aber mit flexibler Semantik

Welche Arten von Implementationen gibt es für Deque<E>?

ArrayDeque, ConcurrenLinkedDeque, LinkedBlockingDeque, LinkedList etc

Wie sieht die Implementation einer ArrayDeque<Temperatur>?

(siehe Bild)

Nutzung der ArrayDeque als Stack: FILO-Semantik, führt zu einer Umkehr der Reihenfolge

Wie ist das Interface Map aufgebaut?

Spezielle Datenstruktur für Schlüssel-Wert-Paare (key-value-pairs):

Erlaubt die Ablage eines Elementes (value) unter einem eindeutigen Schlüssel (key)
Beispiele: Personalnummer und Person, Symbol und Element

(siehe Bild)

Was sind Eigenschaften einer Map<K,V>

Definiert eine Map mit Schlüssel vom Typ K (key) und für Werte vom Typ V (value)

Ein Schlüssel muss inerhalb einer Map eindeutig sein (Schlüssel werden intern als Set<K> abgelegt

Sowohl Wert als auch Schlüssel dürfen auch null sein  (nur einmal pro Map). Ein Wert-Objekt kann mehrfach in einer Map abgespeicher werden (unter verschiedenen Schlüsseln)

Kann man Schlüssel-Objekte in einer Map<K,V> nach dem Einfügen verändern?

Ja, sollte man aber nicht!

Tipp: Für die Bearbeitung entnehmen und danach neu einfügen

Welche Arten von Implementationen gibt es für eine Map<K,V>?

EnumMap, HashMap, HashTable, Properties, TreeMap etc

Zeige eine Implementation einer HashMap<String, Temperatur>

(siehe Bild)

Die Schlüssen dürfen (als Set) keine Duplikate enthalten. Darum wird mit dem zweiten put() mit dem Key "second" der bereits enthaltene Value (das Temperatur-Objekt) ersetzt

Was bedeutet es wenn eine Implementation einer Collection nicht synchronisiert ist?

Sie ist nicht für parallele Zugriffe vorgesehen (-> dafür schneller)

Kann ein wichtiges Kriterium für die Auswahl einer bestimmten Implementation sein

Sehr häufig werden wir bei Elementmengen alle Elemente "durchgehen" (iterieren) wollen, z.B. um sie einzeln zu Bearbeiten, Filtern oder Suchen, etc.

Was ist hierbei jedoch das Problem?
Was gibt es für Lösungen?

Nicht alle Datenstrukturen erlauben einen direkten Zugriff per Index (z.B. verkettete Liste oder Baumstrukturen) Trotzdem möchten wir oft alle Elemente traversieren können!

Die Lösung: Iteratoren

Was machen Iteratoren?

Sie erlauben das Traversieren einer Collection ohne Bezug auf die konkrete Art der Datenstruktur zu nehmen!

Jedes in der Collection enthaltene Element wird während einer Iteration genau einmal zurückgegeben

Dank Polymorphie kommt jeweils der adäquat angepasste Algorithmus (-> Iterator) für jede Datenstruktur zum Einsatz

Welche zwei Varianten von Iteratoren gibt es?

Iterator - kann nur vorwärts traversieren
ListIterator - kann vorwärts und rückwarts traversieren

(siehe Bild)

ListIterator ist nur auf ausgewählten Datenstrukturen verfügbar

Zeige ein Beispiel eines Iteratoren für eine ArrayList<Temperatur> list

Das Interface Collection verlangt eine Methode iterator() mit welcher man einen Iterator beziehen kann (für jede Iteration neuen Iterator beziehen!)

(siehe Bild)

Was ist bei der Methode next() eines Iterators zu beachten?

Die Methode next() ist konsumierend, das heisst sie liefert ein Element und geht gleichzeitig zum Nächsten.

Darum Referenz wenn nötig in einer lokalen Variable für mehrfachen Gebrauch zwischenspeichern (wie im Bild gezeigt)

Wie sieht das Iterator-Pattern nach GoF aus?

Konkrete Implementationen stellen jeweils einen zu ihnen passenden, konkreten Iterator zur Verfügung

(siehe Bild)

Es gibt für fixed-size-arrays und Datenstrukturen, welche Iteratoren unterstützen eine vereinfachte Syntax.

Wie sieht diese aus?

(siehe Bild)

Diese Syntax vermeidet nicht nur typische Fehler, sondern ist auch wesentlich leichter verständlich -> Verwendung empfohlen!

Wichtig: Der Compiler übersetzt diese Syntax in eine ganz normale, klassische while-Schleife mit Iterator, auf welchen man jedoch keinen Zugriff hat

Bei Verwendung von Iteratoren ist darauf zu achten, dass man die zugrundeliegende Datenstruktur während dessen nicht verändert! 

Was bedeutet dies konkret?

- kein Einfügen neuer Elemente
- keine Änderung enthaltener Elemente
- kein Entfernen enthaltener Elemente

Verwendet man einen Iterator um ein Element zu suchen, um dieses zu entfernen, gibt es eine spezielle Methode.

Welche?

remove()

Wie manipuliert man Datenstrukturen?

Mittels statischer Methoden von der Klasse Collections lassen sich ausgewählte Datenstrukturen einfach sortieren: (siehe Bild)

Für spezielle Sortierungen steht eine sort()-Methode zur Verfügung, welcher zusätzlich eine Comparator-Klasse entgegen nimmt

Welche grundlegende Fehlerarten bzw. -kategorien gibt es?

1. Nicht behebbare Fehler. OutOfMemoryError
2. Durch reine Wiederholung (temporär Netzwerkunterbruch)
3. Durch aktive Korrektur (Unbekannter Hostname)

Was ist der Grundsatz der Fehlerbehandlung?

Fehler so nahe an der Quelle wie möglich, und so weit davon entfernt wie nötig behandeln!
Jeh näher, je mehr Informationen sind noch vorhanden.

Für jeden einzelnen Fehler sollte explizit was betrachtet werden?

- Wie ist er zu behandeln?
- Wo soll er behandelt werden? (auf welcher Ebene)
- Ist die Delegation an eine höhere Ebene sinnvoll (Softwareschichten)?
- Macht eine Nachfrage beim/der Benutzerin sinn?
- Muss die Verarbeitung / das Programm abgebrochen werden?

Wie signalisieren wir Fehler?

Wir verwenden den Rückgabewert einer Methode, um zu signalisieren, ob eine Aktion erfolgreich war oder nicht.

Beispiel: public boolean login(String uid, String pwd) {...}

Der Rückgabewert (boolean) sagt aus, ob das Login funktioniert hat oder nicht (für einfache Szenarien durchaus geeignet.

Was passiert, wenn wir eine Folge von Aufgaben haben, die einzeln misslingen können und voneinander abhängig sind? (siehe Bild)

Was das Fehlerhandling aus dem Beispiel macht (siehe Bild)

Was ist das Hauptproblem, wenn wir eine Folge von Aufgaben haben, die einzeln misslingen können und voneinander abhängig sind und wir dadurch folgendes Fehlerhandling erhalten?

Was wäre besser?

Der Quellcode wird sehr unübersichtlich.
- die Fehlerbehandlung dominiert den Quellcode
- der eigentliche Wesenskern wird geradezu verschleiert
- der Rückgabewert wird für den Fehlerstatus "verschwendet"
- oder noch schlimmer: Mit dem Resultat vermischt!

Bilanz: Nachteile überwiegen.
Bessere Lösung: Exceptions (Ausnahmebehandlung)

Wie funktionieren Exceptions?

Im Fehlerfall werden Exceptions erzeugt, mit Informationen bestückt und vonder Fehlerquelle "geworfen" (throw)

Exceptions können zur Behandlung "gefangen" (catch) werden, oder aber auch "weitergereicht" (throws) oder neu geworfen werden (rethrowing)

Was ist ein Vorteil des Exceptionhandlings?

Mit guten Exceptionhandling wird der Code übersichtlicher (Aber: Exceptions sind auch kein Allheilmittel!)

Wie sieht das vereinfachte Konzept der Exceptions aus (Codebeispiel)

Fehler werden auf logischer Ebene explizite als Ausnahmen (Exceptions) definiert und meist zusammengefasst behandelt

Nenne die Schlüsselwörter und deren Kurzbeschreib zum Exceptionhandling

throw - löst eine Exception aus
throws - reicht eine Exception an die nächst höhere Aufrufebene weiter
try - Markiert einen Block in welchem Exceptions erwartet werden, die man "fangen" (behandeln) will
catch - markiert einen Block für die Behandlung eines spezifischen Exceptiontyps (Klasse)
finally - markiert einen optionalen Block der immer ausgeführt wird

Welche Basis-Exceptions stehen in Java zur Verfügung?

ErrorExceptionRuntimeException

Für eigene Exceptions spezialisieren wir typisch Exception oder RuntimeException, selten von ErrorThrowable ist tabu!

(siehe Bild)

Was sind die wichtigsten Methoden der Klasse Throwable und was ist diese Klasse?

Throwable ist die Basisklasse aller Exceptions
getMessage() - Liefert Zusatzinformationen zu einer Exception als String (für Ausgabe)
- getCause() - Liefert ursprüngliche, auslösende Ausnahme (kann ganze Kette sein)
printStackTrace(...) / getStackTrace(...) - Ermöglichen Zugriff auf Ein- und Ausgabe des Stacktrace

Die gelb markierten Konstruktoren sollten bei eigenen Exceptiontypen in der Regel überschrieben werden. (siehe Bild)