O'Reilly logo

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Der Weg zum Java-Profi, 2nd Edition

Book Description

  • Basiert auf jahrelanger Tätigkeit als Softwareentwickler- Vermeiden von Fallstricken und Vermittlung von Best-Practices bei der Programmierung- Fundierter Überblick über Profithemen, die man sonst nicht in Java-Büchern findet. - 21 *-Rezensionen / 3000 Ex in 1 Jahr

Table of Contents

  1. Cover
  2. Titel
  3. Impressum
  4. Inhaltsverzeichnis
  5. Vorwort zur 2. Auflage
    1. Danksagung
    2. Anregungen und Kritik
  6. 1 Einleitung
    1. 1.1 Über dieses Buch
      1. 1.1.1 Motivation
      2. 1.1.2 Was leistet dieses Buch und was nicht?
      3. 1.1.3 Wie und was soll mithilfe des Buchs gelernt werden?
      4. 1.1.4 Wer sollte dieses Buch lesen?
    2. 1.2 Aufbau des Buchs
      1. 1.2.1 Gliederung des Buchs
      2. 1.2.2 Kapitelübersicht
        1. Teil I – Java-Grundlagen, Analyse und Design
        2. Teil II – Bausteine stabiler Java-Applikationen
        3. Teil III – Fallstricke und Lösungen im Praxisalltag
        4. Teil IV – Qualitätssicherungsmaßnahmen
        5. Teil V – Anhang
    3. 1.3 Konventionen
      1. Verwendete Zeichensätze
      2. Verwendete Abkürzungen
      3. Verwendete Java-Umgebungen und -Versionen
      4. Verwendete Klassen aus dem JDK
      5. Sourcecode und ausführbare Programme
    4. 1.4 Danksagungen
      1. Anregungen und Kritik
  7. Teil I Java-Grundlagen, Analyse und Design
    1. 2 Professionelle Arbeitsumgebung
      1. 2.1 Vorteile von IDEs am Beispiel von Eclipse
      2. 2.2 Projektorganisation
        1. Projektstruktur
      3. 2.3 Einsatz von Versionsverwaltungen
        1. Motivation für Versionsverwaltungen
        2. 2.3.1 Arbeiten mit Versionsverwaltungen
          1. Arbeitsablauf
          2. Inhalt des Repository
        3. 2.3.2 Tagging und Branching
          1. Tagging
          2. Branching
          3. Tipps für die Arbeit mit Branches
        4. 2.3.3 CVS und SVN im Vergleich
          1. Versionierung
          2. Arbeitsvorgänge
          3. Tagging und Branching
      4. 2.4 Einsatz eines Unit-Test-Frameworks
        1. 2.4.1 Das JUnit-Framework
          1. Unit Tests mit JUnit 3
          2. Unit Tests mit JUnit 4
        2. 2.4.2 Schreiben und Ausführen von Tests
          1. Fazit
      5. 2.5 Debugging
        1. Notwendige Informationen für eine sinnvolle Fehlersuche
        2. 2.5.1 Fehlersuche mit einem Debugger
          1. Aktionen beim Debugging
        3. 2.5.2 Remote Debugging
          1. Parametrierung der JVM zum Remote Debugging
          2. Remote Debugging in Eclipse an einem Beispiel
          3. Fazit
      6. 2.6 Einsatz eines IDE-unabhängigen Build-Prozesses
        1. 2.6.1 Motivation für ein IDE-unabhängiges Build-System
        2. 2.6.2 Ant-Build
          1. Motivation eines Ant-Builds
          2. Grundgerüst einer build.xml
          3. Einstellungen
          4. Vorbereiten der Verzeichnisse
          5. Löschen eines alten Kompilier- und Release-Standes
          6. Kompilieren des Sourcecodes
          7. Ausführen von Unit Tests
          8. Starten des kompilierten Sourcecodes
          9. Erzeugen einer neuen Auslieferung
          10. Ausblick: Maven
          11. Fazit
      7. 2.7 Weiterführende Literatur
        1. Versionsverwaltungen
        2. Build-Verwaltung
    2. 3 Objektorientiertes Design
      1. 3.1 OO-Grundlagen
        1. 3.1.1 Grundbegriffe
        2. 3.1.2 Beispielentwurf: Ein Zähler
          1. Entwurf à la »Schnell-Finger«
          2. Entwurf à la »Überleg-Erst-Einmal«
          3. Vergleich der Lösungen
          4. Erweiterbarkeit
          5. Fazit
        3. 3.1.3 Diskussion der OO-Grundgedanken
          1. Datenkapselung und Trennung von Zuständigkeiten
          2. Vererbung und Wiederverwendbarkeit
          3. Overriding und Overloading
        4. 3.1.4 Wissenswertes zum Objektzustand
          1. Der Objektzustand am Beispiel
          2. Invarianten, Vor- und Nachbedingungen
          3. Veränderungen am Objektzustand
          4. Weitere Komplexitäten durch Multithreading
          5. Objektzustände während der Objektkonstruktion
      2. 3.2 Grundlegende OO-Techniken
        1. 3.2.1 Abstrakte Basisklassen
          1. Bewertung
        2. 3.2.2 Schnittstellen (Interfaces)
          1. Namensgebung von Interfaces
          2. Bewertung
        3. 3.2.3 Interfaces und abstrakte Basisklassen
          1. Bewertung
      3. 3.3 Vom imperativen zum objektorientierten Entwurf
        1. Entwurf mit verschiedenen Entwurfsstilen
          1. Vergleich der Realisierungen
          2. Mögliche Probleme bei Erweiterungen
      4. 3.4 Fortgeschrittenere OO-Techniken
        1. 3.4.1 Read-only-Interface
          1. Bewertung
          2. Probleme trotz Read-only-Interface durch die Referenzsemantik von Java
          3. Lösungsmöglichkeiten für die »Schlupflöcher«
        2. 3.4.2 Immutable-Klasse
          1. Umgang mit veränderlichen gespeicherten Werten
          2. Bewertung
        3. 3.4.3 Probleme durch Vererbung
          1. Umgang mit Erweiterungen
          2. Wissenswertes zu Vererbung und Wiederverwendbarkeit
          3. Abstrakte vs. konkrete Basisklassen
          4. Fazit
        4. 3.4.4 Delegation statt Vererbung
          1. Klassenexplosion durch Modellierung von Eigenschaften
          2. Klassenexplosion durch Modellierung von Rollen
          3. Bewertung
        5. 3.4.5 Marker-Interface
          1. Bewertung
        6. 3.4.6 Konstantensammlungen, Aufzählungen und das Enum-Muster
          1. Konstantensammlungen
          2. Aufzählungstypen gemäß dem ENUM-Muster
          3. Aufzählungstypen mit dem Schlüsselwort enum
          4. Kombination von Eigenschaften mithilfe der Klasse EnumSet
        7. 3.4.7 Value Object
          1. Anmerkungen
          2. Bewertung
      5. 3.5 Formen der Varianz
        1. 3.5.1 Grundlagen der Varianz
          1. Vorbetrachtungen
          2. Kovarianz: Auswirkungen auf Arrays
          3. Einfluss von Varianz beim Überschreiben von Methoden
        2. 3.5.2 Kovariante Rückgabewerte
      6. 3.6 Generische Typen (Generics)
        1. 3.6.1 Einführung
          1. Typsichere, generische Container
          2. Definition eigener generischer Klassen
        2. 3.6.2 Generics und Auswirkungen der Type Erasure
          1. Fehlende Typinformationen und keine eigenständigen Klassen
          2. Probleme beim Erzeugen von generischen Objekten
          3. Probleme bei der Definition generischer statischer Variablen
          4. Probleme bei der Definition generischer Arrays
          5. Probleme beim Erzeugen generischer Arrays
        3. 3.6.3 Containerklassen: Generics und Varianz
          1. Generics und Polymorphie
          2. Mögliche Probleme durch Kovarianz
          3. Warum ist Kovarianz so wünschenswert?
          4. Kovarianz – Upper Type Bound
          5. Kontravarianz – Lower Type Bound
          6. Invarianz
          7. Auswirkungen der Varianzformen
          8. Unterschied zwischen List, List<Object> und List<?>
      7. 3.7 Weiterführende Literatur
    3. 4 Java-Grundlagen
      1. 4.1 Die Klasse Object
        1. Beispielklasse Person
        2. 4.1.1 Die Methode toString()
          1. Mechanismen bei Ausgaben über System.out.println()
          2. Verbesserungen der toString() -Methode für die Klasse Person
          3. Verbesserungen der toString() -Ausgabe für Arrays
        3. 4.1.2 Die Methode equals()
          1. Die Rolle von equals() beim Suchen
          2. Der equals()-Kontrakt
          3. Typische Fehler bei der Implementierung von equals()
          4. Behandlung optionaler Attribute in equals()
          5. Erweiterungen für equals() in Subklassen
          6. Fazit
      2. 4.2 Primitive Datentypen und Wrapper-Klassen
        1. Interne Darstellung und das Zweierkomplement
        2. 4.2.1 Konvertierung von Werten
          1. Weitere Konvertierungen
          2. Beispiel: Parsen von Zahlen
          3. Wissenswertes zu Auto-Boxing und Auto-Unboxing
          4. Auto-Boxing und Arrays
          5. Fazit
        3. 4.2.2 Ausgabe und Verarbeitung von Zahlen
          1. Ausgabe von Zahlen
          2. Konvertierung von Gleitkommazahlen in eine Bitdarstellung
          3. Extraktion einzelner Bytes aus einem int
          4. Fazit
      3. 4.3 Stringverarbeitung
        1. 4.3.1 Die Klasse String
          1. Wissenswertes zu Stringliteralen und Stringvergleichen
          2. Überraschungen bei Berechnungen in Stringausgaben
          3. Besonderheiten beim Ersatz von toLowerCase() und toUpperCase()
          4. Unveränderlichkeit von Strings
        2. 4.3.2 Die Klassen StringBuffer und StringBuilder
        3. 4.3.3 Ausgaben mit format() und printf()
          1. Ausgaben mit String.format() aufbereiten
          2. Ausgaben mit System.out.printf()
        4. 4.3.4 Die Klasse StringTokenizer
          1. Beispiel: Extraktion einer Versionsnummer
        5. 4.3.5 Die Methode split() und das 1x1 der regulären Ausdrücke
          1. Einfache Zeichenfolgen als regulärer Ausdruck
          2. Varianten in regulären Ausdrücken
          3. Bereichsangaben und Wiederholungen in regulären Ausdrücken
          4. Spezialzeichen in regulären Ausdrücken
          5. Fallstricke beim Ersetzen eines StringTokenizer durch split()
          6. Fazit
      4. 4.4 Datumsverarbeitung
        1. 4.4.1 Fallstricke der Datums-APIs
        2. 4.4.2 Das Date-API
          1. Vergleich von Datumswerten mit dem Date-API
          2. Berechnungen von Datumswerten mit dem Date-API
        3. 4.4.3 Das Calendar-API
          1. Aufbereitung für eine Ausgabe als String
          2. Berechnungen von Datumswerten mit dem Calendar-API
      5. 4.5 Interfaces und innere Klassen
        1. Strukturierung durch Packages
        2. 4.5.1 Interfaces
          1. Innere Interfaces
        3. 4.5.2 Varianten innerer Klassen
          1. »Normale« innere Klassen
          2. Statische innere Klassen
        4. 4.5.3 Designbeispiel mit inneren Klassen und Interfaces
        5. 4.5.4 Lokal definierte Klassen und Interfaces
          1. Beispiel
      6. 4.6 Ein- und Ausgabe (I/O)
        1. 4.6.1 Dateibehandlung und die Klasse File
          1. Pfad-Aktionen
          2. File-Aktionen
          3. Die Interfaces FileFilter und FilenameFilter
          4. Beispiel: Verzeichnisüberwachung
        2. 4.6.2 Ein- und Ausgabestreams
          1. Die Klassen InputStream und Reader
          2. Die Klassen OutputStream und Writer
          3. Eigene Erweiterungen der Klassen der I/O-Bibliotheken
          4. Zeichencodierungen mit InputStream und OutputStream verarbeiten
        3. 4.6.3 Speichern und Laden von Daten und Objekten
          1. Einsatz der Klassen FileInputStream und FileOutputStream
          2. Einsatz der Klassen DataInputStream und DataOutputStream
          3. Ausgaben mit der Klasse PrintStream
          4. Die Klasse Scanner
          5. Fazit
        4. 4.6.4 Grundlagen der Netzwerkprogrammierung
          1. Schnellüberblick Netzwerkprotokolle
          2. Kommunikation über Sockets
          3. Aufbau einer Verbindung zu einem Server
          4. Realisierung eines Servers
          5. Demonstration der Kommunikation
          6. Fazit
      7. 4.7 Fehlerbehandlung
        1. Reaktion auf Fehlersituationen
        2. Rückgabewerte vs. Exceptions
        3. 4.7.1 Exception Handling
          1. Sicheres Exception Handling am Beispiel
        4. Checked Exceptions und Unchecked Exceptions
        5. 4.7.2 Assertions
          1. Assertions am Beispiel
          2. Tipps zum Einsatz von Assertions
      8. 4.8 Weiterführende Literatur
  8. Teil II Bausteine stabiler Java-Applikationen
    1. 5 Das Collections-Framework
      1. 5.1 Datenstrukturen
        1. 5.1.1 Wahl einer geeigneten Datenstruktur
          1. Wahl einer Datenstruktur basierend auf dem Interface Collection
          2. Wahl einer Datenstruktur basierend auf dem Interface Map
          3. Erweiterungen in JDK 5 und 6
        2. 5.1.2 Arrays
        3. 5.1.3 Das Interface Collection
          1. Mengenoperationen auf Collections
          2. Traversierung von Collections über das Interface Iterator
          3. Löschfunktionalität im Interface Iterator
        4. 5.1.4 Listen und das Interface List
          1. Das Interface List
          2. Das Interface ListIterator
          3. Arbeitsweise der Klassen ArrayList und Vector
          4. Arbeitsweise der Klasse LinkedList
        5. 5.1.5 Mengen und das Interface Set
          1. Beispiel für den Einsatz von Mengen
        6. 5.1.6 Grundlagen von hashbasierten Containern
          1. Realisierung in Java
          2. Füllgrad (Load Factor)
          3. Auswirkungen von Größenanpassungen
          4. Die Rolle von hashCode() beim Suchen
          5. Der hashCode() -Kontrakt
          6. Typische Fehler bei der Implementierung der Methode hashCode()
          7. Entwurf einer Utility-Klasse zur Berechnung von hashCode()
        7. 5.1.7 Grundlagen automatisch sortierender Container
          1. Arbeitsweise sortierender Datenstrukturen
          2. Das Interface Comparable und die Methode compareTo()
          3. Das Interface Comparator
          4. Grundgerüst eines einfachen Komparators
        8. 5.1.8 Die Methoden equals(), hashCode() und compareTo() im Zusammenspiel
        9. 5.1.9 Konkrete Realisierungen von Mengen
          1. Die Klasse HashSet
          2. Die Klasse LinkedHashSet
          3. Die Klasse TreeSet
        10. 5.1.10 Schlüssel-Wert-Abbildungen und das Interface Map
          1. Das Interface Map
          2. Die Klasse HashMap
          3. Die Klasse LinkedHashMap
          4. Die Klasse TreeMap
        11. 5.1.11 Erweiterungen am Beispiel der Klasse HashMap
        12. 5.1.12 Entscheidungshilfe zur Wahl von Datenstrukturen
      2. 5.2 Suchen, Sortieren und Filtern
        1. 5.2.1 Suchen
          1. Suchen mit contains()
          2. Suchen mit indexOf() und lastIndexOf()
          3. Suchen mit binarySearch()
        2. 5.2.2 Sortieren mit Komparatoren
          1. Definition eines Komparators (nach Name)
          2. Definition eines Komparators (nach Alter)
          3. Definition zusammengesetzter Komparatoren
          4. Zusammengesetzte Komparatoren
          5. Hintereinanderschaltung von Komparatoren
          6. Umkehren der Sortierreihenfolge per Comparator
        3. 5.2.3 Filtern von Collections
          1. Grundlagen
          2. Vergleiche
          3. Logische Verknüpfungen
          4. Spezialisierungen für verschiedene Datentypen
          5. Die Filter im Einsatz
          6. Erweiterung
          7. Fazit
      3. 5.3 Utility-Klassen und Hilfsmethoden
        1. 5.3.1 Nützliche Hilfsmethoden
          1. Arrays.asList()
          2. Collections.singletonList()
          3. Collections.emptyList()/emptyMap()/emptySet()
        2. 5.3.2 Dekorierer synchronized, unmodifiable und checked
          1. synchronized-Collections
          2. unmodifiable-Collections
          3. checked-Collections
        3. 5.3.3 Vordefinierte Algorithmen
          1. Die Methoden nCopies() und frequency()
          2. Die Methoden min() und max()
          3. Die Methoden shuffle() und replaceAll()
        4. 5.3.4 Design eines Zugriffsinterface
          1. Aufgabenkontext und Anforderungsdefinition
          2. Realisierung eines direkten Zugriffs
          3. Realisierung einer spezialisierten Zugriffsmethode
          4. Realisierung mithilfe eines Iterators
          5. Ergebnismenge vs. Iterator
          6. Gefahr von Inkonsistenzen ohne Iterator
      4. 5.4 Probleme im Collections-Framework
        1. 5.4.1 Merkwürdigkeiten in Arrays
          1. Arrays und Vergleiche
          2. Arrays und clone()
        2. 5.4.2 Probleme von Stack, Queue und Deque
          1. Problematische Realisierung der Klasse Stack
          2. Unklarheiten im Interface Queue
          3. Unklarheiten im Interface Deque
      5. 5.5 Weiterführende Literatur
    2. 6 Applikationsbausteine
      1. 6.1 Einsatz von Bibliotheken am Beispiel
        1. Beispiel: Konvertierung eines Byte-Arrays in eine Liste von Strings
        2. Schreiben einiger Unit Tests
        3. Vereinfachung durch Nutzung der JDK-Klassen String + Arrays
        4. Mögliche weitere Verbesserungen
        5. Fazit
      2. 6.2 Wertebereichs- und Parameterprüfungen
        1. 6.2.1 Prüfung einfacher Wertebereiche und Wertemengen
          1. Prüfen einer Wertemenge
          2. Erstellen erster Unit Tests
        2. 6.2.2 Prüfung komplexerer Wertebereiche
          1. Definition zusammenhängender Wertebereiche in einer Klasse
          2. Probleme beim Erstellen einer generischen Kopie
          3. Problem 1: Fallstricke beim Konstruktoraufruf und der Initialisierung
          4. Einsatz der Klasse ValueRange in der Utility-Klasse RangeCheckUtils
          5. Erstellen von Unit Tests
          6. Erweiterung auf nicht zusammenhängende Wertebereiche
          7. Erweiterung der Unit Tests
          8. Nützliche weitere Methoden
          9. Fazit und Ausblick
      3. 6.3 Logging-Frameworks
        1. Vorteile von Logging-Frameworks
        2. 6.3.1 Apache log4j
          1. log4j-Grundbegriffe
          2. Zusammenspiel von Logger, Appender und Layout
          3. Log-Konfiguration
        3. 6.3.2 Tipps und Tricks zum Einsatz von Logging mit log4j
          1. Abfrage der Log-Level
          2. Verwende logische Log-Kategorien
          3. Logging der Aufrufe an Schnittstellen zu anderen Systemen
          4. Automatische Auswertungsmöglichkeiten
          5. Verwende mehrere unterschiedliche Konfigurationsdateien
          6. Logging von Strings
          7. Logging mit Datumswerten
          8. Logging von Exceptions
          9. Stacktrace ausgeben
          10. Sonderbehandlung spezieller Exceptions
      4. 6.4 Utility-Klassen zur Dateibehandlung
        1. 6.4.1 Die Klasse FileUtils
          1. Sicherstellen der Existenz eines speziellen Verzeichnispfads
          2. Erleichterungen beim Filtern von Verzeichnissen
          3. Erleichterungen bei der Verarbeitung von Dateiendungen
        2. 6.4.2 Die Klasse StreamUtils
          1. Methode close() und IOException
          2. Realisierung einer Copy-Funktionalität
          3. Gepuffertes Kopieren
          4. Verallgemeinerung
          5. Convenience zur Vermeidung von mehrfacher Pufferung
          6. Fazit
        3. 6.4.3 Implementierung von Stringstreams
          1. Implementierung einer Klasse StringInputStream
          2. Implementierung einer Klasse StringOutputStream
      5. 6.5 Konfigurationsparameter und -dateien
      6. Format und Umwandlung der Konfigurationswerte
        1. 6.5.1 Einlesen von Kommandozeilenparametern
          1. Notationsformen für Parameter
          2. Auswertung von Parametern
          3. Apache Commons CLI
        2. 6.5.2 Verarbeitung von Properties
          1. Erste Realisierung mit der Klasse Properties
          2. Umsetzung der Verbesserungswünsche
          3. Fazit
          4. Bewertung der Klasse Properties
        3. 6.5.3 Die Klasse Preferences
          1. Speicherung von Konfigurationsdaten
          2. Hierarchische Struktur
          3. Einstellungen ermitteln
          4. Einstellungswerte setzen und holen
        4. 6.5.4 Weitere Möglichkeiten zur Konfigurationsverwaltung
          1. Beispiel: Einlesen von Highscores aus einer CSV-Datei
          2. Einsatz einer Bibliothek
    3. 7 Multithreading
      1. Grundlagen zu Parallelität und Nebenläufigkeit
      2. 7.1 Threads und Runnables
        1. 7.1.1 Definition der auszuführenden Aufgabe
        2. 7.1.2 Start, Ausführung und Ende von Threads
          1. Starten von Threads
          2. Ausführen von Threads
          3. Ende der Ausführung von Threads
          4. Thread-Prioritäten
          5. Threads und Thread-Gruppen
        3. 7.1.3 Lebenszyklus von Threads und Thread-Zustände
          1. Unterbrechungswünsche durch Aufruf von interrupt() äußern
          2. Entwurf einer Utility-Klasse
      3. 7.2 Zusammenarbeit von Threads
        1. 7.2.1 Konkurrierende Datenzugriffe
        2. 7.2.2 Locks, Monitore und kritische Bereiche
          1. Kritische Bereiche und das Schlüsselwort synchronized
          2. Analogie von Synchronisationsobjekt und synchronized-Methode
        3. 7.2.3 Deadlocks und Starvation
          1. Deadlocks
          2. Starvation
        4. 7.2.4 Kritische Bereiche und das Interface Lock
          1. Grundlagen von Locks
          2. Parallelität durch den Einsatz von Read-Write-Locks
          3. Beispiel: synchronized durch Locks ersetzen
      4. 7.3 Kommunikation von Threads
        1. 7.3.1 Kommunikation mit Synchronisation
        2. 7.3.2 Kommunikation über die Methoden wait(), notify() und notifyAll()
          1. Producer-Consumer mit wait(), notify() und notifyAll()
          2. Erweiterung auf mehrere Consumer
          3. Erweiterung auf eine Größenbeschränkung
          4. Bedingungen und das Interface Condition
        3. 7.3.3 Abstimmung von Threads
          1. Die Methoden isAlive() und join()
          2. Kommunikation über einen Semaphor
        4. 7.3.4 Unerwartete IllegalMonitorStateExceptions
          1. Lock-Klassen und IllegalMonitorStateExceptions
      5. 7.4 Das Java-Memory-Modell
        1. 7.4.1 Sichtbarkeit
        2. 7.4.2 Atomarität
          1. Atomare Variablen als Lösung?
        3. 7.4.3 Reorderings
          1. Hintergrundinformationen zur Ordnung hb
      6. 7.5 Besonderheiten bei Threads
        1. 7.5.1 Verschiedene Arten von Threads
          1. main-Thread und User-Threads
          2. Daemon-Threads
        2. 7.5.2 Exceptions in Threads
        3. 7.5.3 Sicheres Beenden von Threads
          1. Hilfsklasse zum Beenden
          2. Beenden mit interrupt()
          3. Fazit
        4. 7.5.4 Zeitgesteuerte Ausführung
          1. Ausführung einer Aufgabe mit den Klassen Timer und TimerTask
          2. Fazit
      7. 7.6 Die Concurrency Utilities
        1. 7.6.1 Concurrent Collections
          1. Thread-Sicherheit und Parallelität mit »normalen« Collections
          2. Thread-Sicherheit und Parallelität mit den Concurrent Collections
          3. Blockierende Warteschlangen und das Interface BlockingQueue
          4. Beispiel: Producer-Consumer mit BlockingQueue
        2. 7.6.2 Das Executor-Framework
          1. Das Interface Executor
          2. Motivation für Thread-Pools
          3. Das Interface ExecutorService
          4. Callables und Runnables
          5. Ausführen von Runnable und Callable: Das Future-Interface
          6. Parallele Abarbeitung im ExecutorService
          7. Mehrere Tasks abarbeiten
          8. ScheduledExecutorService vs. Timer
          9. Fazit
      8. 7.7 Weiterführende Literatur
    4. 8 Fortgeschrittene Java-Themen
      1. 8.1 Crashkurs Reflection
        1. Hinweise zum Einsatz
        2. 8.1.1 Grundlagen
          1. Ermitteln von Metadaten zu Klassen
          2. Der erste Methodenaufruf per Reflection
        3. 8.1.2 Zugriff auf Methoden und Attribute
          1. Methoden ermitteln
          2. Eigenschaften ermitteln
          3. Attribute ermitteln
          4. Beispiel: Informationen aufbereiten
        4. 8.1.3 Spezialfälle
          1. Aufruf von Konstruktoren
          2. Übergabe von primitiven Datentypen an Konstruktoren oder Methoden
          3. Objektkonstruktion und primitive Typen am Beispiel
          4. Zugriff auf private Methoden und Werte statischer Attribute
          5. Fazit
      2. 8.2 Annotations
        1. 8.2.1 Einführung in Annotations
        2. 8.2.2 Standard-Annotations des JDKs
        3. 8.2.3 Definition eigener Annotations
          1. Meta-Annotations
        4. 8.2.4 Annotation zur Laufzeit auslesen
          1. Fazit
      3. 8.3 Serialisierung
        1. 8.3.1 Implementieren der Serialisierung
          1. Der Serialisierungsvorgang im Detail
        2. 8.3.2 Die Serialisierung anpassen
          1. Problemkontext
          2. Modifikation des Serialisierungsvorgangs
        3. 8.3.3 Versionsverwaltung der Serialisierung
        4. 8.3.4 Optimierung der Serialisierung
          1. Optimierung durch eigene Repräsentationsform
          2. Das Interface Externalizable
          3. Fazit
      4. 8.4 Objektkopien und das Interface Cloneable
        1. Erwartungshaltung
        2. 8.4.1 Das Interface Cloneable
          1. Grundlagen zur Methode clone()
          2. Der clone() -Kontrakt
          3. Erste Schritte mit der clone() -Methode
          4. Hilfreiche, wünschenswerte API-Erleichterungen
          5. Mögliche Probleme bei Vererbung
          6. Spezialbehandlungen für Container
        3. 8.4.2 Alternativen zur Methode clone()
          1. Objektkopien mit einem Copy-Konstruktor erstellen
          2. Objektkopien mithilfe von Serialisierung erstellen
      5. 8.5 Internationalisierung
        1. 8.5.1 Grundlagen
          1. Sprache
          2. Land und Region
          3. Zahlen
          4. Währungen
          5. Datum und Uhrzeit
        2. 8.5.2 Die Klasse Locale
          1. Zugriff auf alle verfügbaren Locale-Objekte
          2. Einsatz der Klasse
        3. 8.5.3 Die Klasse PropertyResourceBundle
          1. Definition verschiedener Sprachdateien
          2. Einlesen der Texte
          3. Zugriff auf die Texte
          4. Beispiel
          5. Ausblick
        4. 8.5.4 Formatierte Ein- und Ausgabe
          1. Überblick über die Format-Klassen
        5. 8.5.5 Zahlen und die Klasse NumberFormat
          1. Formatierte Ausgabe
          2. Beispiel
          3. Parsen von Strings – Umwandlung in Number-Objekte
        6. 8.5.6 Datumswerte und die Klasse DateFormat
          1. Formatierte Ausgabe
          2. Parsen von Strings – Umwandlung in Date-Objekte
          3. Einsatz von SimpleDateFormat für Anpassungen
        7. 8.5.7 Textmeldungen und die Klasse MessageFormat
          1. Erweiterungen der Formatspezifikation
          2. Fazit
        8. 8.5.8 Stringvergleiche mit der Klasse Collator
          1. Die Klasse Collator
          2. Beispiel
          3. Vergleich im Detail steuern
          4. Optimierung des Vergleichs
      6. 8.6 Programmbausteine zur Internationalisierung
        1. 8.6.1 Unterstützung mehrerer Datumsformate
          1. Auswertung von Datumsformaten
          2. Erweiterung: Einlesen von Formatstrings aus einer Property-Datei
          3. Fazit
        2. 8.6.2 Nutzung mehrerer Sprachdateien
          1. Verwaltung der Sprachdateien mit der Klasse ResourceManager
          2. Einsatz der Klasse ResourceManager
          3. Initialisierung vorhandener Sprachdateien
          4. Unterstützung und Umschaltung aller vorhandenen Sprachdateien
          5. Erweiterung: Parametrierte Sprachbausteine
          6. Fazit und Ausblick
      7. 8.7 Garbage Collection
        1. Automatik vs. manueller Aufruf
        2. 8.7.1 Einflussfaktoren auf die Garbage Collection
          1. Aufteilung des Speichers
          2. Varianten der Garbage Collection
        3. 8.7.2 Algorithmen zur Garbage Collection
          1. Mark-and-Sweep-Algorithmus
          2. Stop-and-Copy-Algorithmus
          3. Mark-and-Compact-Algorithmus
        4. 8.7.3 Optimierungen der Garbage Collection
          1. Anpassungen des Perm-Bereichs
        5. 8.7.4 Memory Leaks: Gibt es die auch in Java?!
        6. 8.7.5 Objektzerstörung und finalize()
      8. 8.8 Weiterführende Literatur
    5. 9 Programmierung grafischer Benutzeroberflächen
      1. 9.1 Grundlagen zu grafischen Oberflächen
        1. Überblick
        2. Bedienelemente
        3. Container
        4. Layoutmanagement
        5. Ereignisbehandlung
        6. 9.1.1 Überblick: Bedienelemente und Container
          1. Wissenswertes zum Beispiel
          2. Nützliche Container im Überblick
        7. 9.1.2 Einführung in das Layoutmanagement
          1. Motivation für Layoutmanager
          2. Überblick über einige vordefinierte Layoutmanager des JDKs
          3. Layoutmanager im Einsatz
        8. 9.1.3 Komplexere Layouts durch Kombination von Layoutmanagern
          1. Typisches Layout
          2. Hierarchische Struktur
          3. Implementierung
        9. 9.1.4 Grundlagen zur Ereignisbehandlung
          1. Wichtige Interfaces und Klassen bei der Ereignisbehandlung
          2. Verarbeitung von Events
          3. Grundlagen zum Event-Loop
        10. 9.1.5 Gebräuchliche Event Listener
          1. Besonderheiten beim Schließen von Fenstern
          2. WindowListener – Verarbeitung von WindowEvents
          3. ComponentListener – Verarbeitung von ComponentEvents
          4. MouseListener und MouseMotionListener – Verarbeitung von MouseEvents
          5. KeyListener – Verarbeitung von KeyEvents
        11. 9.1.6 Varianten der Ereignisverarbeitung
          1. Listener-Klasse als anonyme Klasse
          2. Listener-Klasse als (statische) innere Klasse
          3. Listener-Klasse als separate Klasse
          4. Listener-Implementierung durch Komponentenklasse
          5. Fazit
      2. 9.2 Multithreading und Swing
        1. 9.2.1 Crashkurs Event Handling in Swing
          1. Einstellen von Aktionen mit invokeLater() bzw. invokeAndWait()
        2. 9.2.2 Ausführen von Aktionen
          1. Synchron im EDT
          2. Verzögert im EDT
          3. Parallel zum EDT
        3. 9.2.3 Die Klasse SwingWorker
          1. Wichtige Methoden der Klasse SwingWorker
          2. Fazit
      3. 9.3 Zeichnen in GUI-Komponenten
        1. 9.3.1 Generelles zum Zeichnen in GUI-Komponenten
          1. Grundsätzliches zum Zeichnen und Neuzeichnen
          2. Abmessungen, Koordinatensystem und Grafikkontext
          3. Die Klasse FontMetrics
          4. Fazit
        2. 9.3.2 JTextField mit Markierungslinien
          1. Realisierung des JTextFields mit Markierungslinien
          2. Erweiterung um Längenprüfung
          3. Fazit
        3. 9.3.3 Einführung in Java 2D
          1. Figuren mit der Klasse Path2D erstellen
          2. Java 2D am Beispiel
          3. Transparenzeffekte
          4. Clipping
          5. Drucken mit dem Java Printing API
        4. 9.3.4 Bedienelemente mit Java 2D selbst erstellen
          1. Schritt 1: Außenring und Hintergrund zeichnen
          2. Schritt 2: Der Zeiger und seine Verankerung
          3. Schritt 3: Die Skala
          4. Schritt 4: Die GUI-Komponente TachoControl
          5. Schritt 5: Ein kleines Testprogramm
          6. Fazit
      4. 9.4 Komplexe Bedienelemente
        1. 9.4.1 Grundlagen
          1. Model-View-Controller
          2. Datenmodelle
          3. View – Darstellung mit Renderern
          4. Fazit
        2. 9.4.2 Die Klasse JList
          1. Interfaces und Klassen im Zusammenspiel mit einer JList
          2. Selektionen
          3. Datenmodell
          4. Renderer
          5. Verarbeitung dynamischer Listeninhalte
        3. 9.4.3 Die Klasse JTable
          1. Interfaces und Klassen im Zusammenspiel mit einer JTable
          2. Datenmodell
          3. Anpassungen der Spalten im TableColumnModel
          4. Renderer
          5. Sortierbarkeit mit TableRowSorter
          6. Filterung
          7. Veränderlichkeit einzelner Zellen und Editoren
          8. Verarbeitung dynamischer Tabelleninhalte
        4. 9.4.4 Die Klasse JTree
          1. Interfaces und Klassen im Zusammenspiel mit JTree
          2. Baumstrukturen
          3. Das Modell und die Klasse TreeModel
          4. Benachrichtigungen und Selektion
          5. Renderer
          6. Veränderlichkeit der Daten in Bäumen
      5. 9.5 Weiterführende Literatur
    6. 10 Einführung in Persistenz und Datenbanken
      1. 10.1 Grundlagen zur Persistenz
        1. 10.1.1 Beschränkungen einfacher Persistenzlösungen
        2. 10.1.2 Modelle zur Persistierung von Objekten
          1. Darstellung von Objekten als n-Tupel
          2. Objekte als Einträge in Tabellen relationaler Datenbanken
        3. 10.1.3 Wissenswertes zur Speicherung von Daten in Tabellen relationaler Datenbanken
          1. Eindeutigkeit und Identifizierung von Datensätzen
          2. Redundanzfreiheit und Normalisierung
          3. Datenkonsistenz und Transaktionen
          4. Datenschutz und Datensicherheit
        4. 10.1.4 Abbildung zwischen Objekt- und Datenbank-Modell
          1. Einführendes Beispiel
          2. Abbildung von Referenzen
          3. Abbildung von Assoziationen und Aggregationen
          4. Abbildung von Vererbung
          5. Fazit
        5. 10.1.5 Die Datenbanksysteme Java DB und HSQLDB
          1. Datenbankanbindung und Datenbanktreiber
          2. Java DB
          3. HSQLDB
        6. 10.1.6 SQL-Grundlagen
          1. DDL – Definition von Tabellen
          2. DQL – Datenabfrage
          3. DML – Datenmanipulation
          4. Fazit
      2. 10.2 Datenbankzugriffe per JDBC
        1. Einführendes Beispiel zur Datenbankabfrage
        2. 10.2.1 Schritte zur Abfrage von Datenbanken
          1. 1. JDBC-Datenbanktreiber laden
          2. 2. Datenbankverbindung aufbauen
          3. 3. SQL-Anweisungsobjekt erzeugen
          4. 4. SQL-Anweisung ausführen
          5. 5. Ergebnisse auswerten
          6. 6. SQL-Anweisungsobjekt schließen
          7. 7. Datenbankverbindung schließen
        3. 10.2.2 Umgang mit Fehlern
          1. Aufräumarbeiten übersichtlich gestalten
        4. 10.2.3 Besonderheiten von ResultSet
          1. Konfiguration eines ResultSets
          2. Absolute und relative Positionierung
          3. Änderungen an ResultSets
          4. Umgang mit NULL-Werten
        5. 10.2.4 Abfrage von Metadaten
          1. Ermittlung von Metadaten
          2. Metadaten als Grundlage für ein Swing-Tabellenmodell
          3. Einsatz des Swing-Tabellenmodells im SQL-Abfrage-Tool
        6. 10.2.5 Probleme bei der Ausführung von Statements
          1. Schwachstellen der Ausführung mit Statements
          2. Weitere Nachteile von Statements
        7. 10.2.6 Das Interface PreparedStatement
          1. SQL-Anweisungen mit PreparedStatements ausführen
          2. Ausführung komplexerer PreparedStatements
        8. 10.2.7 Transaktionen in JDBC
          1. Der Auto-Commit-Modus und seine Schwächen
          2. Benutzerdefinierte Transaktionssteuerung
          3. Isolationsgrade von Transaktionen
      3. 10.3 Grundlagen zum ORM mit JDBC
        1. 10.3.1 Rekonstruktion von Objekten
          1. Einfache Rekonstruktion – alle Personen-Datensätze ermitteln
          2. Partielle Rekonstruktion – Adressen zu einer Person ermitteln
          3. Vollständige Rekonstruktion – Person inklusive Adressen ermitteln
        2. 10.3.2 Zugriffe mit einem Data Access Object (DAO)
          1. Realisierung eines DAOs für die Klasse Person
      4. 10.4 Datenbanken und JPA
        1. 10.4.1 Grundlagen zum ORM und zum Java Persistence API
          1. Wissenswertes zum OR-Mapping
          2. Vorarbeiten für Hibernate
          3. Einführung in das Java Persistence API
        2. 10.4.2 Persistente Klassen
          1. Konfiguration des Datenbankzugriffs – persistence.xml
        3. 10.4.3 Datenbankzugriffe per JPA
          1. Anbindung an die Datenbank
          2. Vorteile der rein konfigurativen Persistenz
          3. Basisfunktionalität eines EntityManagers
        4. 10.4.4 DAO-Funktionalität und die Klasse EntityManager
          1. Einsatz des DAOs
        5. 10.4.5 Spezialfälle des ORMs per JPA
          1. Abbildung von Assoziationen (1:1,1:n, n:m)
          2. Abbildung von Vererbungshierarchien
          3. Fazit
      5. 10.5 Weiterführende Literatur
    7. 11 Neuerungen in JDK 7
      1. 11.1 Erweiterungen der Sprache selbst
        1. Vereinfachungen bei Typangaben
        2. switch mit Strings
        3. Multi Catch
        4. Final Rethrow
        5. Automatic Resource Management (ARM)
        6. Binäre Literale
        7. Unterstriche in numerischen Literalen
      2. 11.2 Erweiterungen des NIO in JDK 7
        1. 11.2.1 Dateibehandlung in JDK 7
          1. Das Interface Path
          2. Das Interface DirectoryStream
          3. Das Interface BasicFileAttributes
          4. Das Interface FileVisitor
          5. DirectoryObserver basierend auf JDK 7
        2. 11.2.2 Asynchronous I/O
      3. 11.3 Multithreading
        1. Die Concurrent Collections und die TransferQueue
        2. Das Fork-Join-Framework
      4. 11.4 Neuerungen in AWT und Swing
        1. Beispielapplikation
        2. Neuerungen im Farbauswahldialog
      5. 11.5 Collections
        1. Optimierung des Sortieralgorithmus
        2. Hilfsklasse Collections
      6. 11.6 Der Garbage Collector »G1«
        1. Arbeitsweise
  9. Teil III Fallstricke und Lösungen im Praxisalltag
    1. 12 Bad Smells
      1. Bad Smells am Beispiel
      2. 12.1 Programmdesign
        1. 12.1.1 Bad Smell: Verwenden von Magic Numbers
        2. 12.1.2 Bad Smell: Konstanten in Interfaces definieren
        3. 12.1.3 Bad Smell: System.exit() mitten im Programm
        4. 12.1.4 Bad Smell: Zusammengehörende Konstanten nicht als Typ definiert
        5. 12.1.5 Bad Smell: Programmcode im Logging-Code
        6. 12.1.6 Bad Smell: Unvollständige Betrachtung aller Alternativen
        7. 12.1.7 Bad Smell: Unvollständige Änderungen nach Copy-Paste
        8. 12.1.8 Bad Smell: Casts auf unbekannte Subtypen
        9. 12.1.9 Bad Smell: Pre-/Post-Increment in komplexeren Statements
        10. 12.1.10 Bad Smell: Keine Klammern um Blöcke
        11. 12.1.11 Bad Smell: Variablendeklaration nicht im kleinstmöglichen Sichtbarkeitsbereich
        12. 12.1.12 Bad Smell: Mehrere aufeinanderfolgende Parameter gleichen Typs
        13. 12.1.13 Bad Smell: Grundloser Einsatz von Reflection
      3. 12.2 Klassendesign
        1. 12.2.1 Bad Smell: Unnötigerweise veränderliche Attribute
        2. 12.2.2 Bad Smell: Aufruf abstrakter Methoden im Konstruktor
          1. Variante
          2. Verstecktere Initialisierungsprobleme
        3. 12.2.3 Bad Smell: Herausgabe von this im Konstruktor
        4. 12.2.4 Bad Smell: Referenzierung von Subklassen in Basisklassen
        5. 12.2.5 Bad Smell: Mix abstrakter und konkreter Basisklassen
        6. 12.2.6 Bad Smell: Öffentlicher Defaultkonstruktor lediglich zum Zugriff auf Hilfsmethoden
      4. 12.3 Fehlerbehandlung und Exception Handling
        1. 12.3.1 Bad Smell: Unbehandelte Exception
        2. 12.3.2 Bad Smell: Unpassender Exception-Typ
        3. 12.3.3 Bad Smell: Exceptions zur Steuerung des Kontrollflusses
        4. 12.3.4 Bad Smell: Fangen der allgemeinsten Exception
          1. Ausnahmen
          2. Vereinfachungen mit JDK 7
        5. 12.3.5 Bad Smell: Rückgabe von null statt Exception im Fehlerfall
        6. 12.3.6 Bad Smell: Unbedachte Rückgabe von null
          1. Ausbreitung dieses Bad Smells
        7. 12.3.7 Bad Smell: Sonderbehandlung von Randfällen
        8. 12.3.8 Bad Smell: Keine Gültigkeitsprüfung von Eingabeparametern
        9. 12.3.9 Bad Smell: Fehlerhafte Fehlerbehandlung
          1. Spezialfälle
        10. 12.3.10 Bad Smell: I/O ohne finally bzw. finalize()
          1. Spezialfall: Ressourcenattribute
        11. 12.3.11 Bad Smell: Resource Leaks durch Exceptions im Konstruktor
          1. Fazit
      5. 12.4 Häufige Fallstricke
        1. Fallstrick: Nutzung statischer Attribute statt Membervariablen
        2. Fallstrick: Änderung statischer Attribute im Konstruktor/in Methoden
        3. Fallstrick: Missachtung der Initialisierungsreihenfolge statischer Attribute
        4. Fallstrick: Utility-Klasse mit öffentlichem Konstruktor
        5. Fallstrick: Chaotische Konstruktor-/Methoden-Aufruffolgen
        6. Fallstrick: Einsatz von Vererbung und statischen Methoden
        7. Fallstrick: Missverständliches API durch Überladen
        8. Fallstrick: Mehrfachverkettung der ».«-Notation
        9. Fallstrick: Unnötige Komplexität
        10. Fallstrick: Objektvergleich durch Einsatz von toString()und equals()
        11. Fallstrick: Rückgabe von null in toString()-Methoden
        12. Fallstrick: Zugriff ohne Bereichsprüfung
          1. Fallstrick: Intensive Nutzung von Sprungmarken, break und continue
        13. Fallstrick: default mitten in den case-Anweisungen versteckt
        14. Fallstrick: Berechnungen in case-Anweisungen
        15. Fallstrick: Einsatz komplizierter boolescher Bedingungen
        16. Fallstrick: Einsatz doppelter Verneinung
        17. Fallstrick: Kommentierte Klammern
      6. 12.5 Weiterführende Literatur
        1. Bad Smells und Merkwürdigkeiten im Java-API
    2. 13 Refactorings
      1. Refactorings am Beispiel
      2. Schritt 1: Erstellen von Testfällen
      3. Schritt 2: Vereinfachungen durch Zusammenfassen der Bedingungen
      4. Schritt 3: Einsatz der Java-Bibliotheken zum Parsen von Zahlen
      5. Schritt 4: Behandlung ungültiger null-Eingabewerte
      6. 13.1 Das Standardvorgehen
        1. Beispiel
        2. Fazit
      7. 13.2 Der Refactoring-Katalog
        1. 13.2.1 Reduziere die Sichtbarkeit von Attributen
          1. Schritt 1: Erzeugen von Zugriffsmethoden
          2. Schritt 2: Sichtbarkeit des Attributs reduzieren
          3. Schritt 3: Korrekturen der Verwendungsstellen
          4. Schritt 4: Wiederhole Schritte 1 bis 3 für alle Attribute
          5. Fazit
          6. Sinnvolle weitere Schritte
        2. 13.2.2 Minimiere veränderliche Attribute
          1. Schritt 1: Prüfe, auf Schreibzugriffe – Definiere ein Attribut final
          2. Schritt 2: Prüfe, ob die set() -Methode entfernt werden kann
          3. Schritt 3: Prüfen interner Schreibzugriffe
          4. Schritt 4: Anpassung des Konstruktors
          5. Schritt 5: Wiederhole Schritt 1 bis 4 für alle Attribute
          6. Fazit
          7. Sinnvolle weitere Schritte
        3. 13.2.3 Reduziere die Sichtbarkeit von Methoden
          1. Einschränkungen
        4. 13.2.4 Ersetze Mutatordurch Business-Methode
        5. 13.2.5 Minimiere Zustandsänderungen (Refactoring-Kombination)
        6. 13.2.6 Führe ein Interface ein
          1. Einschränkungen
        7. 13.2.7 Aufspalten eines Interface
        8. 13.2.8 Einführen eines Read-only-Interface
        9. 13.2.9 Einführen eines Read-Write-Interface
        10. 13.2.10 Einführen von Convenience-Methoden
          1. Schritt 1: Erzeugen von Hilfsmethoden
          2. Schritt 2: Anpassen der Aufrufstellen
          3. Fazit
        11. 13.2.11 Einführen einer Zustandsprüfung
          1. Schritt 1: Implementieren einer Prüfmethode
          2. Schritt 2: Einsatz der Prüfmethode
          3. Fazit
        12. 13.2.12 Überprüfung von Eingabeparametern
          1. Schritt 1: Referenz- oder Bereichsprüfung
          2. Schritt 2: Einsatz von Aufzählungen, wenn sinnvoll und möglich
          3. Schritt 3: Angabe übergebener Werte und von Gültigkeitsbereichen
          4. Schritt 4: Herausfaktorieren von Prüfmethoden
          5. Fazit
        13. 13.2.13 Trenne Informationsbeschaffung und -verarbeitung
          1. Schritt 1: Erkennen von veränderlichen Elementen und Einführen von Hilfsvariablen
          2. Schritt 2: Zusammenfassen der set()-Methoden zu Blöcken
          3. Schritt 3: Auftrennen von Informationsbeschaffung und -verarbeitung
          4. Schritt 4: Kapseln von Informationsbeschaffung und -verarbeitung
          5. Fazit
        14. 13.2.14 Konstantensammlung in enum umwandeln
          1. Schritt 1: Sammlung in einer eigenen Konstantenklasse
          2. Schritt 2: Erzeugen eines Konstruktors und von Zugriffsmethoden
          3. Schritt 3: Umwandlung in eine enum-Aufzählung
          4. Fazit
        15. 13.2.15 Entferne Exceptions zur Steuerung des Kontrollflusses
          1. Schritt 1: Einführen eines Rückgabewerts
          2. Schritt 2: Exception Handling durch Auswertung des Rückgabewerts ersetzen
          3. Optionale Optimierungen zur Lesbarkeit
          4. Fazit
        16. 13.2.16 Umwandlung in Utility-Klasse mit statischen Hilfsmethoden
          1. Schritt 1: Umwandlung in statische Hilfsmethode
          2. Schritt 2: Erweiterung der Methodensignatur
          3. Schritt 3: Umwandlung aller Methoden in entsprechende Hilfsmethoden
          4. Schritt 4: Entfernen von Zustandsinformationen und anpassen von Konstruktoren
          5. Fazit
      8. 13.3 Weiterführende Literatur
    3. 14 Entwurfsmuster
      1. Design mit Entwurfsmustern
      2. Beispielapplikation: Image-Editor
      3. 14.1 Erzeugungsmuster
        1. 14.1.1 Erzeugungsmethode
          1. Beschreibung und Motivation
          2. Struktur
          3. Erweiterungen
          4. Bewertung
        2. 14.1.2 Fabrikmethode (Factory method)
          1. Beschreibung und Motivation
          2. Struktur
          3. Beispiel
          4. Bewertung
        3. 14.1.3 Erbauer (Builder)
          1. Beschreibung und Motivation
          2. Struktur
          3. Beispiel
          4. Bewertung
        4. 14.1.4 Singleton
          1. Beschreibung und Motivation
          2. Struktur
          3. Beispiel
          4. Bewertung
        5. 14.1.5 Prototyp (Prototype)
          1. Beschreibung und Motivation
          2. Struktur
          3. Beispiel
          4. Bewertung
      4. 14.2 Strukturmuster
        1. 14.2.1 Fassade (Façade)
          1. Beschreibung und Motivation
          2. Struktur
          3. Bewertung
        2. 14.2.2 Adapter
          1. Beschreibung und Motivation
          2. Struktur
          3. Beispiel
          4. Bewertung
        3. 14.2.3 Dekorierer (Decorator)
          1. Beschreibung und Motivation
          2. Struktur
          3. Beispiel
          4. Bewertung
        4. 14.2.4 Kompositum (Composite)
          1. Beschreibung und Motivation
          2. Struktur
          3. Beispiele
          4. Bewertung
      5. 14.3 Verhaltensmuster
        1. 14.3.1 Iterator
          1. Beschreibung und Motivation
          2. Struktur
          3. Beispiel
          4. Allgemeine bzw. polymorphe Iteratoren
          5. Bewertung
        2. 14.3.2 Null-Objekt (Null Object)
          1. Beschreibung und Motivation
          2. Struktur
          3. Beispiel
          4. Bewertung
        3. 14.3.3 Schablonenmethode (Template method)
          1. Beschreibung und Motivation
          2. Struktur
          3. Beispiel
          4. Bewertung
        4. 14.3.4 Strategie (Strategy)
          1. Beschreibung und Motivation
          2. Struktur
          3. Beispiel
          4. Bewertung
        5. 14.3.5 Befehl (Command)
          1. Beschreibung und Motivation
          2. Struktur
          3. Beispiel
          4. Ausführungskontext
          5. Erweiterungen
          6. Bewertung
        6. 14.3.6 Proxy
          1. Beschreibung und Motivation
          2. Struktur
          3. Varianten
          4. Beispiel
          5. Bewertung
        7. 14.3.7 Zuständigkeitskette (Chain of Responsibility)
          1. Beschreibung und Motivation
          2. Struktur
          3. Beispiele
          4. Bewertung
        8. 14.3.8 Beobachter (Observer)
          1. Beschreibung und Motivation
          2. Struktur
          3. Anmerkungen
          4. Beispiel: Warum ist Java-Built-In-Observer ungünstig?
          5. Verbesserungen
          6. Bewertung
        9. 14.3.9 MVC-Architektur
          1. Anmerkungen
          2. Bewertung
      6. 14.4 Weiterführende Literatur
  10. Teil IV Qualitätssicherungsmaßnahmen
    1. 15 Programmierstil und Coding Conventions
      1. 15.1 Grundregeln eines guten Programmierstils
        1. 15.1.1 Keep It Human-Readable
        2. 15.1.2 Keep It Simple And Short
        3. 15.1.3 Keep It Natural
        4. 15.1.4 Keep It Clean
      2. 15.2 Die Psychologie beim Sourcecode-Layout
        1. 15.2.1 Faktor der Ähnlichkeit
        2. 15.2.2 Faktor der Nähe
          1. Beispiel 1
          2. Beispiel 2
      3. 15.3 Coding Conventions
        1. 15.3.1 Grundlegende Namens- und Formatierungsregeln
          1. Ausnahmen für die Formatierung
          2. Namensregeln
        2. 15.3.2 Namensgebung
          1. Vermeide Namenskürzel
          2. Vermeide Variablennamen, die nur den Typ wiederholen
          3. Verwende sinnvolle, konsistente Namen
          4. Benenne Klassen nach ihrer Funktion
          5. Verwende für Containerklassen einen Pluralnamen
        3. 15.3.3 Dokumentation
          1. Verwende kurze, aussagekräftige Kommentare
          2. Vermeide Kommentare, die nur den Ablauf beschreiben
          3. Dokumentiere alle Methoden im öffentlichen Interface der Klasse
        4. 15.3.4 Programmdesign
          1. Halte den Sourcecode sauber
          2. Vermeide Seiteneffekte
          3. Vermeide übermäßige Debug- und Log-Ausgaben
          4. Vermeide Ausgaben per System.out
          5. Verwende final
          6. Vermeide Magic Numbers und Strings
          7. Hilf dem Garbage Collector
          8. Überprüfe Eingabeparameter auf Gültigkeit
          9. Verwende Assertions oder Exceptions zur Zusicherung für Pre- und Post-Conditions
          10. Prüfe Rückgabewerte und behandle Fehlersituationen
          11. Bevorzuge wenige return-Anweisungen
          12. Vermeide die sorglose Rückgabe von null
          13. Prüfe Referenzen auf null
          14. Behandle auftretende Exceptions wenn möglich
          15. Vermeide catch (Exception ex) und catch (Throwable th)
          16. Vermeide return in catch/finally-Blöcken
        5. 15.3.5 Klassendesign
          1. Bevorzuge lokale Variablen gegenüber Attributen
          2. Vermeide statische Attribute
          3. Greife auf Attribute bevorzugt über Methoden zu
          4. Vermeide feingranulare Änderungen am Objektzustand
          5. Liefere keine Referenzen auf interne Datenstrukturen zurück
          6. Minimiere Zustandsänderungen
          7. Programmiere gegen Interfaces oder abstrakte Klassen
          8. Verstecke Implementierungsdetails
          9. Definiere abstrakte Methoden möglichst protected
          10. Sorge für Lesbarkeit und die richtige Abstraktionsebene
          11. Halte das Interface übersichtlich
          12. Vermeide zu viele Referenzen auf andere Klassen
          13. Beachte die maximale Methodenlänge von ca. 30 – 50 Zeilen
          14. Beachte die maximale Klassenlänge von ca. 500 – 1000 Zeilen
        6. 15.3.6 Parameterlisten
          1. Halte die Parameterliste kurz
          2. Vermeide überflüssige Parameter
          3. Vermeide mehrere gleiche Typen aufeinander folgend in der Parameterliste
          4. Halte die Reihenfolge von Parametern bei Methodenaufrufen konsistent
        7. 15.3.7 Logik und Kontrollfluss
          1. Vermeide explizite true-/false-Literale in if-/while-Anweisungen
          2. Verwende möglichst wenige else if-Anweisungen
          3. Verwende nicht mehr als drei bis vier Logikauswertungen in einem if
          4. Verwende den Conditional-Operator mit Bedacht
          5. Fazit
      4. 15.4 Sourcecode-Überprüfung mit Tools
        1. Sourcecode-Checker und statische Analyse
        2. 15.4.1 Metriken
        3. 15.4.2 Sourcecode-Überprüfung im Build-Prozess
          1. Basiskonfiguration für Eclipse
          2. Das Tool Checkstyle
          3. Das Tool PMD
          4. Das Tool FindBugs
          5. PMD vs. FindBugs
          6. Das Tool Metrics
    2. 16 Unit Tests
      1. 16.1 Überblick
        1. 16.1.1 Arten von Tests
          1. Zuständigkeiten beim Testen
          2. Konkretisierung des Begriffs des Unit Test
        2. 16.1.2 Äußere vs. innere Qualität
        3. 16.1.3 Auswirkungen von Unit Tests auf die Qualität
          1. Auswirkungen von Unit Tests auf das API-Design
          2. Zusammenspiel von Unit Tests und Integrationstests
      2. 16.2 Motivation für Unit Tests aus der Praxis
        1. 16.2.1 Unit Tests für Neuentwicklungen
          1. Auswertung von Statustelegrammen
          2. Schritt 1: Korrekturen der Abhängigkeiten und Lesbarkeit
          3. Schritt 2: Erstellen erster Unit Tests
          4. Schritt 3: Unit Tests um Testfälle A bis F erweitern
          5. Schritt 4: Unit Tests um Testfälle für die Konvertierung 0 bis F erweitern
          6. Schritt 5: Testfälle für Eingabewerte a bis f
          7. Schritt 6: Implementierung erweitern um Konvertierung a bis f
          8. Fazit
        2. 16.2.2 Unit Tests und Legacy-Code
          1. Vorarbeiten: Analyse
          2. Schritt 1: Schreiben von ersten Unit Tests
          3. Schritt 2: Herausfaktorieren einer durch Unit Tests prüfbaren Methode
          4. Schritt 3: Anpassungen für bessere Wart- und Lesbarkeit
          5. Schritt 4: Fehlersuche und -korrektur durch Log-Auswertung
          6. Schritt 5: Komplettierung der Unit Tests
          7. Fazit: Positive Effekte beim Einsatz von Unit Tests
      3. 16.3 Fortgeschrittene Unit-Test-Techniken
        1. 16.3.1 Testen mit Stubs
          1. Vorbereitungen zur Testbarkeit – Lösen von Abhängigkeiten
        2. 16.3.2 Testen mit Mocks
          1. Aufzeichnung von Erwartungen
          2. Durchführung von Tests
          3. Fazit
        3. 16.3.3 Unit Tests von privaten Methoden
      4. 16.4 Unit Tests mit Threads und Timing
        1. Realisierung der Funktionalität
        2. Vorbereitungen zum Test der Klasse MessageConcatenator
        3. Definition von Unit Tests für die Klasse MessageConcatenator
        4. Fazit
      5. 16.5 Nützliche Tools für Unit Tests
        1. 16.5.1 Hamcrest
          1. Hamcrest in Aktion: Der erste Test
          2. Übersicht über die wichtigsten Matcher
          3. Definition eigener Matcher
          4. Generierte Fehlermeldungen
        2. 16.5.2 Infinitest
        3. 16.5.3 Cobertura
          1. Bewertung der Messergebnisse und Ermittlung fehlender Testfälle
          2. Auswirkungen auf die Qualität
          3. Ausführen von Cobertura
      6. 16.6 Weiterführende Literatur
    3. 17 Codereviews
      1. 17.1 Definition
        1. Durchführung
        2. Vorteile
        3. Psychologische Aspekte und Probleme
      2. 17.2 Probleme und Tipps zur Durchführung
      3. 17.3 Vorteile von Codereviews
        1. Fazit
      4. 17.4 Codereview-Tools
        1. Das Tool Code Collaborator
        2. Das Tool Crucible
        3. Das Tool Jupiter
        4. Fazit
      5. 17.5 Codereview-Checkliste
    4. 18 Optimierungen
      1. 18.1 Grundlagen
        1. 18.1.1 Optimierungsebenen und Einflussfaktoren
        2. 18.1.2 Optimierungstechniken
        3. 18.1.3 CPU-bound-Optimierungsebenen am Beispiel
          1. Diskussion
        4. 18.1.4 Messungen – Erkennen kritischer Bereiche
          1. Die »80-zu-20-Regel«
          2. Messungen des Zeitverhaltens
          3. Messungen des Speicherbedarfs
          4. Profiling-Tools
          5. Validierung von Änderungen
          6. Skalierbarkeit
        5. 18.1.5 Abschätzungen mit der O-Notation
          1. Komplexitätsklassen
          2. Auswirkungen der Komplexität auf die Programmlaufzeit
      2. 18.2 Einsatz geeigneter Datenstrukturen
        1. 18.2.1 Einfluss von Arrays und Listen
          1. Die Klassen ArrayList und Vector
          2. Die Klasse LinkedList
          3. Betrachtung von Vor- und Nachteilen
        2. 18.2.2 Optimierungen für Set und Map
          1. HashSet und HashMap
          2. ConcurrentHashMap
          3. TreeSet und TreeMap
          4. ConcurrentSkipListSet und ConcurrentSkipListMap
        3. 18.2.3 API-Design Collection vs. Iterator
      3. 18.3 Lazy Initialization
        1. 18.3.1 Lazy Initialization am Beispiel
          1. Analyse
          2. Einführen von Lazy Initialization
        2. 18.3.2 Konsequenzen des Einsatzes der Lazy Initialization
          1. Synchronisationsprobleme
          2. Initialisierungsprobleme
        3. 18.3.3 Lazy Initialization mithilfe des PROXY-Musters
          1. Empfehlungen
          2. Fazit
      4. 18.4 Optimierungen am Beispiel
        1. Problemkontext
        2. Analyse
        3. I/O-bound-Optimierungen
        4. Memory-bound-Optimierungen
        5. Fazit
      5. 18.5 I/O-bound-Optimierungen
        1. 18.5.1 Technik – Wahl passender Strategien
          1. Optimierungen beim Einsatz von Streams
          2. Kompression und Zip-Archive
          3. Optimierungen der Serialisierung
        2. 18.5.2 Technik – Caching und Pooling
        3. 18.5.3 Technik – Vermeidung unnötiger Aktionen
          1. Optimierungen beim Logging
          2. Reduktion von Remote Calls
      6. 18.6 Memory-bound-Optimierungen
        1. 18.6.1 Technik – Wahl passender Strategien
          1. Größe und Nutzung des Hauptspeichers
          2. Optimierungen der Garbage Collection
        2. 18.6.2 Technik – Caching und Pooling
          1. Objekt-Caching
          2. Objekt-Pools
        3. 18.6.3 Optimierungen der Stringverarbeitung
          1. StringBuffer / StringBuilder als Abhilfe?
          2. Diskussion
        4. 18.6.4 Technik – Vermeidung unnötiger Aktionen
          1. Reduziere die Kosten der Objekterzeugung
          2. Bevorzuge primitive Datentypen
      7. 18.7 CPU-bound-Optimierungen
        1. 18.7.1 Technik – Wahl passender Strategien
        2. 18.7.2 Technik – Caching und Pooling
        3. 18.7.3 Technik – Vermeidung unnötiger Aktionen
      8. 18.8 Weiterführende Literatur
  11. Teil V Anhang
    1. A Einführung in die UML
      1. A.1 Die UML im Überblick
        1. Diagramme der UML
        2. Modellierung und Diagramm-Granularität
        3. Modellierungstools
      2. A.2 Strukturdiagramme – statische Modelle
        1. A.2.1 Klassendiagramme
          1. Elemente von Klassendiagrammen
          2. Beziehungen zwischen Klassen und Interfaces
        2. A.2.2 Objektdiagramme
        3. A.2.3 Komponentendiagramme
        4. A.2.4 Paketdiagramme
      3. A.3 Verhaltensdiagramme – dynamische Modelle
        1. A.3.1 Anwendungsfalldiagramme
          1. Granularität von Anwendungsfalldiagrammen
        2. A.3.2 Sequenzdiagramme
          1. Elemente von Sequenzdiagrammen
        3. A.3.3 Kommunikationsdiagramme
        4. A.3.4 Zustandsdiagramme
          1. Beispiel
        5. A.3.5 Aktivitätsdiagramme
          1. Beispiel
      4. A.4 Weiterführende Literatur
    2. B Überblick über den Softwareentwicklungsprozess
      1. B.1 Vorgehensmodelle
        1. B.1.1 Aufgaben und Phasen beim Softwareentwurf
        2. B.1.2 Wasserfallmodell und V-Modell
          1. Das Wasserfallmodell
          2. Das V-Modell
          3. Probleme beider Modelle
        3. B.1.3 Extreme Programming (XP)
        4. B.1.4 Test-Driven Development (TDD)
        5. B.1.5 Diskussion
    3. C Grundlagen zur Java Virtual Machine
      1. C.1 Wissenswertes rund um die Java Virtual Machine
        1. C.1.1 Ausführung eines Java-Programms
        2. C.1.2 Sicherheit und Speicherverwaltung
        3. C.1.3 Sicherheit und Classloading
  12. Literaturverzeichnis
  13. Index
  14. Fußnoten
    1. Kapitel 2
    2. Kapitel 3
    3. Kapitel 4
    4. Kapitel 5
    5. Kapitel 6
    6. Kapitel 7
    7. Kapitel 8
    8. Kapitel 9
    9. Kapitel 10
    10. Kapitel 11
    11. Kapitel 12
    12. Kapitel 13
    13. Kapitel 14
    14. Kapitel 15
    15. Kapitel 16
    16. Kapitel 18
    17. Anhang A
    18. Anhang B
    19. Anhang C