| 

.NET C# Java Javascript Exception

6
Es ist unglaublich, aber ich habe tatsächlich noch keinen Klassen-Matcher in meinem Blog behandelt. Wenn man öfter mal basierend auf dem Typ eines Wertes verzweigen muss, sieht es oft so aus: Oder noch schlimmer, wenn man sich „sicher“ ist, dass es nur zwei Alternativen gibt: …was natürlich mit einem niedlichen kleinen Atompilz explodiert, wenn dann […]

Es ist unglaublich, aber ich habe tatsächlich noch keinen Klassen-Matcher in meinem Blog behandelt.

Wenn man öfter mal basierend auf dem Typ eines Wertes verzweigen muss, sieht es oft so aus:

Object obj = ...
String s;
if (obj instanceof Integer) {
 s = "int " + (Integer) obj;
} else if (obj instanceof Long) {
 s = "long " + (Long) obj;
} else if (obj instanceof Double) {
 s = "double" + (Double) obj;
} else {
 s = "häh?!?";
}

Oder noch schlimmer, wenn man sich „sicher“ ist, dass es nur zwei Alternativen gibt:

String s = obj instanceof Integer 
 ? "int " + (Integer) obj
 : "long " + (Long) obj; 

…was natürlich mit einem niedlichen kleinen Atompilz explodiert, wenn dann doch etwas anderes in obj steckt.

Wie wäre es dagegen mit dieser Syntax hier:

String s = match(obj,
 when(Integer.class, i -> "int " + i),
 when(Long.class, l -> "long " + l),
 when(Double.class, d -> "double " + d)
 ).orElse("häh?!?");

Die match-Methode liefert ein Optional, so dass man leicht selbst entscheiden kann, wie man auf einen unbekannten Typ reagiert. Die Argumente in den Lambdas sind natürlich typsicher, das i ist z.B. vom Typ Integer. Im Ausgangsbeispiel hat man ein Problem, wenn instanceof-Check und Typcast nicht zusammenpassen – das kann hier nicht passieren.

Die DSL-Klasse, die das ermöglicht, ist erstaunlich kurz:

import java.util.Arrays;
import java.util.Optional;
import java.util.function.Function;

public final class InstanceOf {

 @SafeVarargs
 public static <R> Optional<R> match(Object o, Function<Object, Optional<R>>... cases) {
 return Arrays.stream(cases)
 .map(c -> c.apply(o))
 .filter(Optional::isPresent)
 .findFirst()
 .flatMap(Function.identity());
 }

 public static <T, R> Function<Object, Optional<R>> when(Class<T> clazz, Function<T, R> fn) {
 return obj -> clazz.isAssignableFrom(obj.getClass())
 ? Optional.of(fn.apply((T) obj))
 : Optional.empty();
 }
}

Eigentlich eine Schande, dass man so etwas nicht gleich in Java 8 eingebaut hat.

Dann wünsche ich viel Spaß beim typsicheren Kaskadieren!

uncategorized
Weitere News:
Schreibe einen Kommentar:
Themen:
uncategorized
Entweder einloggen... ...oder ohne Wartezeit registrieren
Benutzername
Passwort
Passwort wiederholen
E-Mail