java.util.Objects

von Hubert Schmid vom 2013-03-10

Die Klasse java.util.Objects wurde mit Java 7 eingeführt und enthält ohne Kommentare gerade mal 40 Zeilen Quelltext. Sowohl die späte Einführung als auch der geringe Umfang erwecken den Eindruck, dass die Klasse nicht sonderlich relevant ist. Doch das täuscht: Die Klasse war längst überfällig und ihr Nutzen wird immer noch unterschätzt. An dieser Stelle gehe ich auf die wichtigsten drei Methoden ein.

Objects.equals

Der Nutzen der statische Methode Objects.equals ist einfach zu motivieren. Dafür muss ich lediglich in Eclipse die folgende Klasse Person anlegen und anschließend von Eclipse die Member-Methode equals generieren lassen.

public class Person { private String lastName; private String firstName; }

Das Ergebnis ist in folgendem Code-Fragment zu sehen. Die Methoden ist lang und unverständlich, und ich möchte solchen Code nicht in meinen Klassen stehen haben.

@Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof Person)) { return false; } Person other = (Person) obj; if (lastName == null) { if (other.lastName != null) { return false; } } else if (!lastName.equals(other.lastName)) { return false; } if (firstName == null) { if (other.firstName != null) { return false; } } else if (!firstName.equals(other.firstName)) { return false; } return true; }

Mit Object.equals lässt sich die zweite Hälfte der Methode in einer einzigen Anweisung zusammenfassen. Der erste Teil der Methode besteht dagegen im Wesentlichen aus einer fragwürdigen Optimierung. Eine handgeschriebene Implementierung könnte daher einfach wie folgt aussehen:

@Override public boolean equals(Object obj) { if (obj instanceof Person) { Person other = (Person) obj; return Objects.equals(lastName, other.lastName) && Objects.equals(firstName, other.firstName); } else { return false; } }

Objects.hashCode

Ganz ähnlich verhält es sich mit Objects.hashCode. Im Vergleich zu equals benötigt Eclipse dafür zwar nur 10 statt 28 Zeilen Quelltext. Doch mit Objects.equals geht es kürzer und verständlicher, wie im anschließenden Code-Fragment zu sehen.

@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((lastName == null) ? 0 : lastName.hashCode()); result = prime * result + ((firstName == null) ? 0 : firstName.hashCode()); return result; } @Override public int hashCode() { return 31 * (31 + Objects.hashCode(lastName)) + Objects.hashCode(firstName); }

Objects.requireNonNull

Die Methode Objects.requireNonNull ist ein möglicher Schritt auf dem Weg aus der NullPointerException-Krise. Ihre Implementierung ist trivial: Sie reicht das übergebene Argument durch und wirft eine NullPointerException, falls dieses null ist. Die Idee ist, Überprüfungen auf null damit viel früher und häufiger durchzuführen, so dass die zu Grunde liegenden Fehler entweder früher entdeckt oder zumindest schneller lokalisiert werden können.

In meinem ursprünglichen Beispiel könnte man den Konstruktor beispielsweise wie folgt implementieren. Dadurch würden null bereits beim Erstellen eines Person-Objekts aufschlagen, und nicht erst bei der Verwendung der Attribute an ganz anderer Stelle.

import static java.util.Objects.requireNonNull; public class Person { private String lastName; private String firstName; public Person(String lastName, String firstName) { this.lastName = requireNonNull(lastName); this.firstName = requireNonNull(firstName); } }

In Summe sind die drei diskutierten Methoden von java.util.Objects lediglich 11 Zeilen lang. In vielen Dritt-Bibliotheken finden sich bereits ähnliche Funktionalitäten. Und dennoch: Die Einführung und Verwendung von java.util.Objects ist bedeutend, weil sie ein gewisse Vereinheitlichung schafft und Abhängigkeiten auf Dritt-Bibliotheken reduziert.