© Excellent backgrounds/Shutterstock.com
Kolumne: Java-Trickkiste

Code ohne Seiteneffekte


Funktionale Programmierung im üblichen Sinne hat zwei zentrale Merkmale: Funktionen und Seiteneffektfreiheit [1]. Funktionen unterstützt Java seit der Einführung von Lambdas, aber das Programmieren ohne Seiteneffekte hat irgendwie den Sprung in die Java-Kultur noch nicht so recht geschafft. Der Artikel stellt dieses Paradigma vor und macht – hoffentlich – Lust darauf.

Video: Java-Concurrency für Fortgeschrittene

Unveränderliche Objekte

Von Seiteneffekten spricht man, wenn ein Stück Code den Zustand verändert oder auf ein Ausgabegerät schreibt, also zum Beispiel ein Attribut auf einen anderen Wert setzt oder System.out.println() aufruft. Puristen verwenden auch die Begriffe „Wirkung“ oder „Nebeneffekt“, aber ich verwende hier in Anlehnung an den englischen Begriff „Side Effect“ das weit verbreitete „Seiteneffekt“. In Java geht seiteneffektfreie Programmierung Hand in Hand mit Klassen, bei denen alle (beobachtbaren) Attribute final sind. Wo nur solche Klassen zum Einsatz kommen, kann Code ja gar keinen Zustand verändern.

Nehmen wir als Beispiel an, wir wollen eine Anwendung zur Planung von Wanderrouten bauen. Wir fangen mit einer Klasse GeoLocation an, die eine geografische Position repräsentiert (Listing 1).

Listing 1

public class GeoLocation { // Vereinfachende Berechnungen: Erde wird als// Kugel behandelt, // Abflachung an den Polen vernachlässigt public static final double ERDUMFANG_KM =40_000; private final double latitude; private final double longitude; public GeoLocation (double latitude, double longitude) { if (latitude > 90 || latitude < -90) { throw new IllegalArgumentException (); } longitude = longitude % 360; if (longitude < 0) longitude += 360; if (longitude > 180) longitude -= 360; this.latitude = latitude; this.longitude = longitude; } public double getLatitude () { return latitude; } public double getLongitude () { return longitude; } public GeoLocation moveEast (double km) { final double atEquator = km / ERDUMFANG_KM * 360; final double latFactor = Math.cos (latitude *Math.PI / 180); return new GeoLocation (latitude, longitude + atEquator / latFactor); } public GeoLocation moveNorth (double km) { final double degrees = km / ERDUMFANG_KM* 360; return new GeoLocation (latitude + degrees, longitude); } ... // weitere nützliche Methoden }

Sie hat Felder für die geografische Breite und Länge und beide sind final. Der Konstruktor initialisiert diese beiden Felder und führt vorher noch eine Bereichsüberprüfung für die Breite und eine Normal...

Neugierig geworden?

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang