Was ist neu in Java 7? Teil 1 – Produktivität

Seite 2: Project Coin

Inhaltsverzeichnis

Eines der bemerkenswertesten Java-Projekte der vergangenen Jahre ist Project Coin. Es ist aus einer Sammlung von Ende Februar bis Ende März 2009 eingebrachten Vorschlägen für Verbesserungen an der Sprache Java hervorgegangen. Aus den knapp 70 Vorschlägen haben es sechs in die nächste Java-Version geschafft. An exponierter Stelle steht die Verwendung von Strings in Switch-Statements. Bisher ging das nur mit primitiven Daten-Typen, ihren Wrappern und Enums. Mit Java 7 lässt sich nun Folgendes realisieren:

  public static int getMonthNumber(String month) {
int monthNumber = 0;
if (month == null) { return monthNumber; }
switch (month.toLowerCase()) {
case "january": monthNumber = 1; break;
// ...
case "november": monthNumber = 11; break;
case "december": monthNumber = 12; break;
default: monthNumber = 0; break;
}
return monthNumber;
}

Das Beispiel vergleicht den String im Switch-Ausdruck via String.equals mit dem im case-Fall und gibt die entsprechende Nummer des Monats zurück. Das ist mit einigem Abstand die am meisten gewünschte Funktion der Entwickler. Ebenfalls neu ist die Möglichkeit, Literale mit einem Unterstrich ("_") zum Zweck der besseren Lesbarkeit zu formatieren. Zudem ist ein neuer Typ hinzugekommen. Es lassen sich nun auch binäre Literale verwenden.

1234_5678
1_2_3_4__5_6_7_8L
0b0001_0010_0100_1000

Nicht vorkommen darf der Unterstrich am Ende und am Anfang eines Literals sowie an zweideutigen Stellen, an denen die Interpretation gefährdet ist, etwa:

_1234
0x_1234
1234_

Am Exception Handling haben die Entwickler ebenfalls zwei lang erwartete Änderungen vorgenommen. Statt der leidigen Aneinanderreihung von Catch-Blöcken kann der Java-Programmierer jetzt mehrere Exceptions in einem Catch-Block fangen. Dabei steht jeweils ein OR-Symbol ("|") zwischen den Exception-Typen. Für alle Typen ist allerdings der gleiche Exception-Parameter zu verwenden.

try {
throwAorB();
} catch (ExceptionA | ExceptionB ex) {
throw ex;
}

Eine Verbesserung der Exception-Analyse zur Compilezeit wurde eingeführt. Das erneute Werfen einer Exception in einem catch Block (re-throw) erzeugt nun ein Objekt vom Typ der ursprünglich geworfenen Exception und nicht mehr vom Typ der gefangenen.

Zur weiteren Unterstützung der neuen Ansätze wurde eine Superklasse eingeführt. Die ReflectiveOperationException lässt sich als catch für ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException und NoSuchMethodException einsetzen.

Die mit Java 5 eingeführten Generics bekommen dank Coin ebenfalls eine kleine Politur, und zwar durch die Einführung des Diamond-Operators ("<...>"). Bisher waren Typen mehrfach redundant zu deklarieren.

Set<Person> persons = new HashSet<Person>();

Dank des Diamond-Operators ist die Deklaration des Sets jetzt einfacher.

Set<Person> persons = new HashSet<>();

Die kleine Änderung führt zu deutlich lesbareren Quellen und verhindert eine Menge Tipparbeit.

Das leidige Handling von Streams und Closable-Ressourcen vereinfacht das sogenannte Automatic Resource Management (ARM) deutlich. Waren bisher beispielsweise allerlei Arten von Streams (InputStream, OutputStream) in einem "try {} catch() {} finally {}"-Block zu schließen, gestaltet sich das mit dem neuen Interface AutoCloseable und den zugehörigen Änderungen im Rahmen der "try-with-resources"-Spezifikation einfach.

private static void close(Closeable closable) {
if (closable != null) {
try {
closable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Selbst der catch-Block ist optional. Erweiterungen an java.lang.Throwable schließen die Ressourcen nach dem try-Block automatisch und unterdrücken eventuell aufgetretene Exceptions. Es lassen sich eine oder mehrere Ressourcen gleichzeitig im try-Block deklarieren.

try (InputStream fis = new FileInputStream(source);
OutputStream fos = new FileOutputStream(target)){
// lesen und schreiben
} // Ressourcen automatisch geschlossen.

Eine Änderung an den Compiler-Warnungen beim Verwenden sogenannter Non-reifiable-Typen (E, List) in Varargs (variable Argumentenzahl an Methoden) erleichtert die Programmierung ebenfalls deutlich. Hat man bisher versucht, eine Varargs-Methode mit solchen Typen aufzurufen, erzeugt der Compiler die Warnung "unchecked". Diese wurde von der Seite des Aufrufers an die der relevanten Methodendeklaration verlagert. Bisher hat der Compiler immer eine "unsafe operation"-Warnung ausgegeben. Jetzt besteht zur Entwicklungszeit die Möglichkeit, mit @SuppressWarnings("varargs") diese zu unterdrücken. Mit der neuen @SafeVarargs-Annotation sind jetzt:

public static <T> List<T> java.util.Arrays.asList(T... a)
public static <T> boolean java.util.Collections.addAll
(Collection<? super T> c, T... elements)
public static <E extends Enum<E>> java.util.EnumSet<E>
EnumSet.of(E first, E... rest)
protected final void javax.swing.SwingWorker.publish(V... chunks)

versehen. Die Methoden sorgen dafür, dass keine Compiler-Warnungen mehr beim Verwenden von Varargs mit Collections ausgelöst werden.