Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.
 
Inhaltsverzeichnis
Vorwort
1 Java ist auch eine Sprache
2 Imperative Sprachkonzepte
3 Klassen und Objekte
4 Der Umgang mit Zeichenketten
5 Eigene Klassen schreiben
6 Objektorientierte Beziehungsfragen
7 Ausnahmen müssen sein
8 Äußere.innere Klassen
9 Besondere Typen der Java SE
10 Generics<T>
11 Lambda-Ausdrücke und funktionale Programmierung
12 Architektur, Design und angewandte Objektorientierung
13 Die Klassenbibliothek
14 Einführung in die nebenläufige Programmierung
15 Einführung in Datenstrukturen und Algorithmen
16 Einführung in grafische Oberflächen
17 Einführung in Dateien und Datenströme
18 Einführung ins Datenbankmanagement mit JDBC
19 Einführung in <XML>
20 Testen mit JUnit
21 Bits und Bytes und Mathematisches
22 Die Werkzeuge des JDK
A Java SE Paketübersicht
Stichwortverzeichnis

Download:
- Beispielprogramme, ca. 20,0 MB
- Übungsaufgaben, ca. 1,8 MB
- Musterlösungen, ca. 0,8 MB

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Java ist auch eine Insel von Christian Ullenbloom
Das umfassende Handbuch
Buch: Java ist auch eine Insel

Java ist auch eine Insel
Rheinwerk Computing
1306 Seiten, gebunden, 11. Auflage
49,90 Euro, ISBN 978-3-8362-2873-2
Pfeil 9 Besondere Typen der Java SE
Pfeil 9.1 Vergleichen von Objekten
Pfeil 9.1.1 Natürlich geordnet oder nicht?
Pfeil 9.1.2 Die Schnittstelle Comparable
Pfeil 9.1.3 Die Schnittstelle Comparator
Pfeil 9.1.4 Rückgabewerte kodieren die Ordnung
Pfeil 9.1.5 Statische und Default-Methoden in Comparator
Pfeil 9.2 Wrapper-Klassen und Autoboxing
Pfeil 9.2.1 Wrapper-Objekte erzeugen
Pfeil 9.2.2 Konvertierungen in eine String-Repräsentation
Pfeil 9.2.3 Von einer String-Repräsentation parsen
Pfeil 9.2.4 Die Basisklasse Number für numerische Wrapper-Objekte
Pfeil 9.2.5 Vergleiche durchführen mit compare(…), compareTo(…), equals(…) und Hashwerten
Pfeil 9.2.6 Statische Reduzierungsmethoden in Wrapper-Klassen
Pfeil 9.2.7 Die Größe eines primitiven Typs in den Wrapper-Konstanten SIZE und BYTES
Pfeil 9.2.8 Behandeln von vorzeichenlosen Zahlen *
Pfeil 9.2.9 Die Klasse Integer
Pfeil 9.2.10 Die Klassen Double und Float für Fließkommazahlen
Pfeil 9.2.11 Die Long-Klasse
Pfeil 9.2.12 Die Boolean-Klasse
Pfeil 9.2.13 Autoboxing: Boxing und Unboxing
Pfeil 9.3 Object ist die Mutter aller Klassen
Pfeil 9.3.1 Klassenobjekte
Pfeil 9.3.2 Objektidentifikation mit toString()
Pfeil 9.3.3 Objektgleichheit mit equals(…) und Identität
Pfeil 9.3.4 Klonen eines Objekts mit clone() *
Pfeil 9.3.5 Hashwerte über hashCode() liefern *
Pfeil 9.3.6 System.identityHashCode(…) und das Problem der nicht eindeutigen Objektverweise *
Pfeil 9.3.7 Aufräumen mit finalize() *
Pfeil 9.3.8 Synchronisation *
Pfeil 9.4 Die Utility-Klasse java.util.Objects
Pfeil 9.5 Iterator, Iterable *
Pfeil 9.5.1 Die Schnittstelle Iterator
Pfeil 9.5.2 Wer den Iterator liefert
Pfeil 9.5.3 Die Schnittstelle Iterable
Pfeil 9.5.4 Erweitertes for und Iterable
Pfeil 9.5.5 Interne Iteration (seit Java 8)
Pfeil 9.5.6 Einen eigenen Iterable implementieren *
Pfeil 9.6 Die Spezial-Oberklasse Enum
Pfeil 9.6.1 Methoden auf Enum-Objekten
Pfeil 9.6.2 Aufzählungen mit eigenen Methoden *
Pfeil 9.6.3 enum mit eigenen Konstruktoren *
Pfeil 9.7 Zum Weiterlesen
 
Zum Seitenanfang

9Besondere Typen der Java SE Zur vorigen ÜberschriftZur nächsten Überschrift

»Einen Rat befolgen heißt, die Verantwortung verschieben.«
– Johannes Urzidil (1896–1970)

Programmieren wir mit Java, nutzen wir oftmals unbewusst Typen aus der Standardbibliothek. Das fällt oft gar nicht auf, da zum einen das Paket java.lang automatisch importiert wird – und damit Typen wie String, Object immer eingebunden sind – und weil zum anderen einiges hinter den Kulissen passiert. Fünf Beispiele:

  • Erweitert eine Oberklasse keine eigene Klasse, so erbt sie automatisch von java.lang.Object.

  • Hängen wir Strings mit + zusammen, erzeugt der Compiler automatisch einen java.lang.StringBuilder, hängt die Segmente mit append(…) zusammen und liefert dann mit toString() einen neuen String.

  • Beim erweiterten for erwartet der Compiler entweder ein Array oder etwas vom Typ Iterable: Von diesen Objekten erfragt er den Iterator und läuft selbstständig durch die Sammlung.

  • Damit try mit Ressourcen verwendet werden kann, erwartet der Compiler ein AutoCloseable und ruft auf diesen Objekten im finally-Block die close()-Methode auf.

  • Bei der Deklaration eines Aufzählungstyps mit enum generiert der Compiler eine von java.lang.Enum abgeleitete Klasse, und die Aufzählungen haben eine Ordnung.

Dieses Kapitel stellt unterschiedliche Typen vor, die in irgendeiner Weise bevorzugt werden, oder eine Sonderstellung in Java einnehmen, weil sie allgegenwärtig sind. Dazu zählen:

  • Vergleichsobjekte

  • Wrapper-Klassen

  • die Basisklasse Object

  • Aufzählungen und die Schnittstellen Iterable und Iterator

  • Aufzählungstypen, enum und die Sonderklasse Enum

 
Zum Seitenanfang

9.1Vergleichen von Objekten Zur vorigen ÜberschriftZur nächsten Überschrift

In vielen Anwendungen spielt die Ordnung von Objekten eine Rolle. Offensichtlich ist das bei der Sortierung, aber auch bei einfacheren Fragen, wie der nach dem größten oder kleinsten Element einer Sammlung. Sollen Objekte in Java verglichen werden, muss es immer eine Ordnung dieser Objekte geben. Das System wird nie selbstständig entscheiden können, und oftmals gibt es mehrere Kriterien. Warum ist zum Beispiel eine Person kleiner als eine andere Person? Weil die eine Person 1,50 Meter groß ist, die andere aber 1,80 Meter, oder weil die eine Person 1 Million Euro auf dem Konto hat und die andere nur 5 Euro?[ 179 ]

 
Zum Seitenanfang

9.1.1Natürlich geordnet oder nicht? Zur vorigen ÜberschriftZur nächsten Überschrift

In Java gibt es zwei unterschiedliche Schnittstellen (in zwei unterschiedlichen Paketen) zur Bestimmung der Ordnung:

  • Comparable: Implementiert eine Klasse Comparable, so können sich die Objekte selbst mit anderen Objekten vergleichen. Da die Klassen im Allgemeinen nur ein Sortierkriterium implementieren, wird hierüber eine so genannte natürliche Ordnung (engl. natural ordering) realisiert.

  • Comparator: Eine implementierende Klasse, die sich Comparator nennt, nimmt zwei Objekte an und vergleicht sie. Ein Comparator für Räume könnte zum Beispiel nach der Anzahl der Personen oder auch nach der Größe in Quadratmetern vergleichen; die Implementierung von Comparable wäre nicht sinnvoll, weil hier nur ein Kriterium natürlich umgesetzt werden kann, ein Raum aber nicht die Ordnung hat.

Zusammenfassend lässt sich sagen: Während Comparable üblicherweise nur ein Sortierkriterium umsetzt, kann es viele Extraklassen vom Typ Comparator geben, die jeweils unterschiedliche Ordnungen definieren.

Comparable und Comparator in der Java-API

Eine Implementierung von Comparable findet sich genau dort, wo eine natürliche Ordnung naheliegt, etwa bei:

  • String

  • BigDecimal, BigInteger, Byte, Character, Double, Float, Integer, Long, Short

  • Date

  • File, URI

  • Enum

  • TimeUnit

Von Comparator finden wir in der API-Dokumentation nur java.text.Collator vermerkt.

Vereinfachtes UML-Diagramm von Comparator und Comparable

Abbildung 9.1Vereinfachtes UML-Diagramm von Comparator und Comparable

 
Zum Seitenanfang

9.1.2Die Schnittstelle Comparable Zur vorigen ÜberschriftZur nächsten Überschrift

Die Schnittstelle Comparable kommt aus dem java.lang-Paket und deklariert eine Methode:

interface java.lang.Comparable<T>

  • int compareTo(T o)
    Vergleicht sich mit einem anderen Objekt.

[+]Hinweis

Wichtig ist neben einer Implementierung von compareTo(…) auch die passende Realisierung in equals(…). Sie ist erst dann konsistent, wenn e1.compareTo(e2) == 0 das gleiche Ergebnis wie e1.equals(e2) liefert, wobei e1 und e2 den gleichen Typ besitzen. Ein Verstoß gegen diese Regel kann bei sortierten Mengen schnell Probleme bereiten; ein Beispiel nennt die API-Dokumentation. Auch sollte die hashCode()-Methode korrekt realisiert sein, denn sind Objekte gleich, müssen auch die Hashwerte gleich sein. Und die Gleichheit bestimmen eben equals(…)/compareTo(…).

e.compareTo(null) sollte eine NullPointerException auslösen, auch wenn e.equals(null) die Rückgabe false liefert. null ist in der Regel nicht größer/kleiner/gleich einem anderen mit compareTo(…) verglichenem Wert, daher ist eine Ausnahme die einzig vernünftige Reaktion.

 
Zum Seitenanfang

9.1.3Die Schnittstelle Comparator Zur vorigen ÜberschriftZur nächsten Überschrift

Die funktionale Schnittstelle Comparator kommt aus dem Paket java.util (nicht wie Comparable aus java.lang) und deklariert eine zwingend zu implementierende Methode:

interface java.util.Comparator<T>

  • int compare(T o1, T o2)
    Vergleicht zwei Argumente auf ihre Ordnung.

[+]Hinweis *

Neben compare(…) deklariert Comparator auch das aus Object bekannte boolean equals(Object obj). Die Methode muss nicht zwingend implementiert werden, da Object ja schon eine Implementierung bereitstellt. Die Methode steht nur deshalb in der Schnittstelle, damit eine API-Dokumentation erklärt, dass equals(…) nur testet, ob zwei Comparator-Objekte gleich sind.

 
Zum Seitenanfang

9.1.4Rückgabewerte kodieren die Ordnung Zur vorigen ÜberschriftZur nächsten Überschrift

Der Rückgabewert von compare(…) beim Comparator bzw. compareTo(…) bei Comparable ist <0, =0 oder >0 und bestimmt so die Ordnung der Objekte. Nehmen wir zwei Objekte o1 und o2 an, deren Klassen Comparable implementieren. Dann gilt folgende Übereinkunft:

  • o1.compareTo( o2 ) < 0

  • o1.compareTo( o2 ) == 0

  • o1.compareTo( o2 ) > 0

o1 ist »kleiner als« o2.

o1 ist »gleich« o2.

o1 ist »größer als« o2.

Ein externer Comparator (symbolisch comp genannt) verhält sich ähnlich:

  • comp.compare( o1, o2 ) < 0

  • comp.compare( o1, o2 ) == 0

  • comp.compare( o1, o2 ) > 0

o1 ist »kleiner als« o2.

o1 ist »gleich« o2.

o1 ist »größer als« o2.

[+]Tipp

Sollen Objekte mit einem Comparator verglichen werden, aber null-Werte vorher aussortiert werden, so ist die statische Methode int compare(T a, T b, Comparator<? super T> c) aus der Klasse Objects nützlich. Die Methode liefert 0, wenn a und b beide entweder null sind oder der Comparator die Objekte a und b für gleich erklärt. Sind a und b beide ungleich null, so ist die Rückgabe c.compare(a, b). Ist nur a oder b gleich null, so hängt es vom Comparator und der Reihenfolge der Parameter ab.

Den kleinsten Raum einer Sammlung finden

Wir wollen Räume ihrer Größe nach sortieren und müssen dafür einen Comparator schreiben (dass Räume Comparable sind, ist nicht angebracht, da es keine natürliche Ordnung für Räume gibt). Daher soll ein externes Comparator-Objekt entscheiden, welches Raum-Objekt nach der Anzahl seiner Quadratmeter größer ist; weniger Quadratmeter bedeuten, der Raum ist kleiner.

Die Raum-Klasse enthält für das kleine Demoprogramm einen parametrisierten Konstruktor, der sich die Quadratmeter merkt, und einen Getter.

Listing 9.1com/tutego/insel/util/Room.java, Room

public class Room {
private int sqm;
public Room( int sqm ) {
this.sqm = sqm;
}
public int getSqm() {
return sqm;
}
}

Ein Raum, aufgebaut durch new Room(100), soll kleiner sein als new Room(1123). Dazu muss der Raum-Comparator auf die Quadratmeter zurückgreifen, andere Kriterien gibt es nicht:

Listing 9.2com/tutego/insel/util/RoomComparatorDemo.java, RoomComparator

class RoomComparator implements Comparator<Room> {
@Override public int compare( Room room1, Room room2 ) {
return Integer.compareTo( room1.getSqm(), room2.getSqm() );
}
}

Die Methode Integer.compare(…) bietet sich für den Vergleich an, alternativ kann auch die Differenz room1.sm - room2.sm der Raumgrößen für eine Vergleichsrückgabe <0, =0 oder >0 eingesetzt werden. Bei Fließkommazahlen funktioniert das nicht, denn (int)(0.10.0), (int)(0.00.1) und (int)(0.00.0) ergeben alle 0, wären also gleich – bei Ganzzahlen ist der Vergleich aber in Ordnung. Daher ist die compare(…)-Methode der Wrapper-Klassen eine gute Wahl.

Mit dem Comparator-Objekt lässt sich eine Raumliste sortieren, vorne steht dann der kleinste Raum:

Listing 9.3com/tutego/insel/util/RoomComparatorDemo.java, RoomComparatorDemo main()

List<Room> list = Arrays.asList(new Room(1123), new Room(100), new Room(123));
Collections.sort( list, new RoomComparator() );
System.out.println( list.get(0).getSqm() ); // 100

[+]Hinweis

Ist ein Comparator mit einer Datenstruktur – wie dem TreeSet oder der TreeMap – verbunden, muss die Comparator-Klasse Serializable (siehe Kapitel 17, »Einführung in Dateien und Datenströme«) implementieren, wenn auch die Datenstruktur serialisiert werden soll.

 
Zum Seitenanfang

9.1.5Statische und Default-Methoden in Comparator Zur vorigen ÜberschriftZur nächsten Überschrift

Die Schnittstelle Comparator bietet ab Java 8 eine ganze Reihe von statischen und Default-Methoden. (In Comparable gibt es übrigens keine statischen oder Default-Methoden.) Besonders interessant sind die Möglichkeiten, mehrere Comparatoren zusammenzubinden.

Beginnen wir mit den einfach zu verstehenden Methoden:

interface java.util.Comparator<T>

  • static <T extends Comparable<? super T>> Comparator<T> reverseOrder()Liefert einen Comparator, der die Sortierreihenfolge umdreht. Entspricht Collections.reverseOrder().

  • default Comparator<T> reversed()Liefert für diesen aktuellen Comparator einen, der die Sortierreihenfolge umdreht.

  • static <T extends Comparable<? super T>> Comparator<T> naturalOrder()
    Liefert einen Comparator, der die natürliche Ordnung von Objekten verwendet, sprich int compare(Comparable<Object> c1, Comparable<Object> c2) ist implementiert als return c1.compareTo(c2);

  • static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator)

  • static <T> Comparator<T> nullsLast(Comparator<? super T> comparator)Liefert für einen gegebenen comparator einen neuen Comparator, der Vergleiche mit null erlaubt und null von der Ordnung her entweder vor oder hinter die anderen Werte setzt.

Aneinanderreihung von Comparatoren

Oftmals ist das Ordnungskriterium aus mehreren Bedingungen zusammengesetzt, wie die Sortierung in einem Telefonbuch zeigt. Erst gibt es eine Sortierung nach dem Nachnamen, dann folgt der Vorname. Um diese mit einem Comparator-Objekt zu lösen, müssen entweder alle Einzelvergleiche in ein neues Comparator-Objekt verpackt werden oder einzelne Comparatoren zu einem »Super«-Comparator zusammengebunden werden. Die zweite Lösung ist natürlich schöner, weil sie die Wiederverwendbarkeit erhöht, denn einzelne Comparatoren können dann leicht für andere Zusammenhänge genutzt werden. Genau für so eine Aneinanderreihung gibt es in Comparator eine nützliche Methode:

interface java.util.Comparator<T>

  • default Comparator<T> thenComparing(Comparator<? super T> other)Wendet erst den eigenen Comparator an, dann den anderen other.

Wir wollen diese thenComparing(…)-Methoden aus Comparator für ein Beispiel nutzen, das eine Liste nach Nach- und Vornamen sortiert.

Listing 9.4com/tutego/insel/util/ComparatorThenComparingDemo.java

package com.tutego.insel.util;

import java.util.*;

public class ComparatorThenComparingDemo {

public static class Person {

public String firstname, lastname;

public Person( String firstname, String lastname ) {
this.firstname = firstname;
this.lastname = lastname;
}

@Override public String toString() {
return firstname + " " + lastname;
}
}

public final static Comparator<Person>
PERSON_FIRSTNAME_COMPARATOR = new Comparator<Person>() {
@Override public int compare( Person p1, Person p2 ) {
return p1.firstname.compareTo( p2.firstname );
}
};

public final static Comparator<Person>
PERSON_LASTNAME_COMPARATOR = new Comparator<Person>() {
@Override public int compare( Person p1, Person p2 ) {
return p1.lastname.compareTo( p2.lastname );
}
};

public static void main( String[] args ) {
List<Person> persons = Arrays.asList(
new Person( "Onkel", "Ogar" ), new Person( "Olga", "Ogar" ),
new Person( "Peter", "Lustig" ), new Person( "Lara", "Lustig" ) );

persons.sort( PERSON_LASTNAME_COMPARATOR );
System.out.println( persons );
persons.sort( PERSON_FIRSTNAME_COMPARATOR );
System.out.println( persons );
persons.sort( PERSON_LASTNAME_COMPARATOR.thenComparing( PERSON_FIRSTNAME_COMPARATOR ) );
System.out.println( persons );
}
}

Die Ausgabe ist:

[Peter Lustig, Lara Lustig, Onkel Ogar, Olga Ogar]
[Lara Lustig, Olga Ogar, Onkel Ogar, Peter Lustig]
[Lara Lustig, Peter Lustig, Olga Ogar, Onkel Ogar]

Vergleichswert extrahieren und Vergleiche anstellen *

Die verbleibenden Methoden in Comparator bieten alle die Spezialität, dass sie besondere Funktionsobjekte annehmen, die den »Schlüssel« für die Vergleiche extrahieren und dann für den Vergleich heranziehen. Mit der neuen Syntax aus Java 8 lassen sich dann sehr kompakte Comparator-Objekte formulieren:

interface java.util.Comparator<T>

  • static <T,U> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator)

  • static <T,U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor)

  • static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor)

  • static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor)

  • static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor)

  • default <U extends Comparable<? super U>> Comparator<T> thenComparing(Function<? super T,? extends U> keyExtractor)

  • default <U> Comparator<T> thenComparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator)

  • default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor)

  • default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor)

  • default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor)

[zB]Beispiel

Das Beispiel mit den Raumvergleichen alternativ formuliert (wir greifen auf eine kompakte Syntax aus Java 8 zurück, die Methodenreferenz heißt, wir kommen in späteren Kapiteln noch einmal detailliert darauf zurück):

Listing 9.5com/tutego/insel/util/ComparatorDemo.java, Ausschnitt

Comparator<Room> comp = Comparator.comparingInt( Room::getSqm );
// kurz für Comparator.comparingInt( (Room r) -> r.getSqm() );
list.sort( comp );

Komplett ohne Implementierung eigener Comparator-Klassen kann dieser Einzeiler mithilfe der Extraktionsfunktionen nach Vor-/Nachnamen sortieren, unter der Voraussetzung, dass es zwei Getter gibt:

persons.sort( Comparator.comparing( Person::getLastname )
.thenComparing( Person::getFirstname ) );

 


Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.

>> Zum Feedback-Formular
<< zurück
 Zum Katalog
Zum Katalog: Java ist auch eine Insel Java ist auch eine Insel
Jetzt bestellen

 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Java SE 8 Standard-Bibliothek
Java SE 8 Standard-Bibliothek


Zum Katalog: Professionell entwickeln mit Java EE 7
Professionell entwickeln mit Java EE 7


Zum Katalog: Schrödinger programmiert Java
Schrödinger programmiert Java


Zum Katalog: Einführung in Java
Einführung in Java


Zum Katalog: Programmieren lernen mit Java
Programmieren lernen mit Java


Zum Katalog: Apps entwickeln für Android 5
Apps entwickeln für Android 5


Zum Katalog: Apps entwickeln mit Android Studio
Apps entwickeln mit Android Studio


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo

 
 


Copyright © Rheinwerk Verlag GmbH 2016
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 
Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de