Blog

Seien Sie sich bewusst, dass Java mit funktionaler Programmierung nicht lasch ist.

Anton Lijcklama à Nijeholt

Aktualisiert Oktober 21, 2025
3 Minuten

Wenn Sie sich an die funktionale Programmierung gewöhnt haben, werden Sie wahrscheinlich die Kompositionsfähigkeit und die Lesbarkeit lieben, die sie Ihrer Codebasis verleiht. Sie fangen vielleicht an, den Code mehr als eine Pipeline oder "Puzzleteile" zu sehen, die Sie zu verbinden versuchen (oder mit anderen Worten: funktionale Komposition). Bei der Verkettung von Methoden in Java können Sie manchmal auf unerwartetes Verhalten stoßen...

Bei dem Kunden, für den ich arbeite, verwenden wir VAVR, eine Bibliothek, die Ihnen bei vielen täglichen Aufgaben der funktionalen Programmierung helfen kann. Eine davon ist die Klasse Option, die eine bessere Version als das standardmäßige Optional in Java ist (siehe: Warum java.util.Optional kaputt ist)

Heute bin ich auf ein Problem gestoßen, bei dem einige Teile meines Mocks ausgelöst wurden, die nicht ausgelöst werden sollten. Es war ein ziemlich einfacher Ablauf:

  • Bestellung nach Kriterien abrufen X
  • Wenn die Bestellung nicht gefunden werden kann, versuchen Sie es mit dem Kriterium Y
  • Wenn die Bestellung immer noch nicht gefunden wird, versuchen Sie die Kriterien Z

Ganz einfach, oder?

@Test
public void test() {
    Option<String> value = Option.<String>none()
        .orElse(doSomething("step 1"))
        .orElse(doSomething("step 2"))
        .orElse(doSomething("step 3"));
    System.out.println(value);
}
public Option<String> doSomething(String message) {
    System.out.println(message);
    return Option.some(message);
}

Was wird das obige Snippet ausgeben?

step 1
step 2
step 3
Some(step 1)

Sie sehen, dass das Endergebnis schließlich Some(Schritt 1) ist, aber in der Zwischenzeit wurden auch ALLE potenziellen Logiken aller anderen Schritte ausgeführt! Das ist definitiv nicht das, was ich beabsichtigte, als ich den obigen Code schrieb...

Wie können wir das beheben? Durch die Rückgabe von Funktionen, die standardmäßig faul sind:

@Test
public void test() {
    Option<String> value = Option.<String>none()
        .orElse(doSomething("step 1"))
        .orElse(doSomething("step 2"))
        .orElse(doSomething("step 3"));
    System.out.println(value);
}
public Function0<Option<String>> doSomething(String message) {
    return () -> {
        System.out.println(message);
        return Option.some(message);
    };
};

Die Ausgabe, die erzeugt wird:

step 1
Some(step 1)

Lektion gelernt? Der Spott hat mir hier den Tag gerettet. Er hat mich auf Dinge aufmerksam gemacht, die definitiv nicht beabsichtigt waren. In der Produktion wäre es wahrscheinlich viel schwieriger gewesen, dies herauszufinden. Das ist auch ein weiterer Grund, warum Sprachen wie Scala besser für die funktionale Programmierung auf der JVM geeignet sind, da der Entwickler jetzt eine höhere kognitive Belastung erfährt, die ihm in keiner Weise hilft. Warum sollten Sie sich dessen bei der Nicht-Laziness in Java überhaupt bewusst sein?

Sehen Sie sich einfach die Scala-Version an:

def doSomething(message: String): Option[String] = {
  System.out.println(message)
  Some(message)
}
def main(args: Array[String]): Unit = {
  val value = None.orElse(doSomething("step 1"))
      .orElse(doSomething("step 2"))
      .orElse(doSomething("step 3"))
  print(value)
}

Gleicher Ablauf und keine kognitive Belastung für den Entwickler. Das ist ein enormer Vorteil, wenn Sie in einer Sprache schreiben, die über bestimmte Grundlagen in Bezug auf Faulheit verfügt (wie Scala). So können Sie sich auf den Ablauf und die Geschäftslogik konzentrieren, anstatt auf Details auf niedriger Ebene. Für den Programmierer, der Funktionen für eine bestimmte Geschäftsdomäne implementieren muss, bringt das nichts, es sei denn, diese Geschäftsdomäne ist hochtechnisch, wo die Kontrolle über Low-Level-Belange wichtig ist.

Warum funktioniert das in Scala auf Anhieb? Wegen etwas, das "By-Name-Parameter" genannt wird. Es handelt sich dabei um eine Kernfunktion der Sprache, die die faule Auswertung zu einem Kinderspiel macht. Wenn Sie weitere Informationen zu diesem Thema wünschen, lesen Sie bitte: TOUR DER SCALA BY-NAME PARAMETER

Ich hoffe, das war nützlich! Wenn Sie noch Fragen haben, lassen Sie es mich bitte wissen!

Verfasst von

Anton Lijcklama à Nijeholt

Contact

Let’s discuss how we can support your journey.