Klassen mit einer abstrakten Methode als funktionale Schnittstelle in Java 8?

Als die Entwickler Lambda-Ausdrücke diskutierten, stand auch die Frage im Raum, ob abstrakte Klassen, die nur über eine abstrakte Methode verfügen – früher wurde hier die Abkürzung SAM (Single Abstract Method) genutzt –, ebenfalls für Lambda-Ausdrücke genutzt werden können. Sie entschieden sich dagegen, da bei Implementierung von Schnittstellen die JVM weitreichende Optimierungen vornehmen kann. Und bei Klassen wir das schwierig, was auch daran liegt, dass ein Konstruktor umfangreiche Initialisierungen mit Seiteneffekten vornehmen (die Konstruktoren aller Oberklassen nicht zu vergessen) sowie Ausnahmen auslösen könnte. Gewünscht ist aber nur die Ausführung einer Implementierung der funktionalen Schnittstelle und kein anderer Code.

Es gibt nun im JDK einige abstrakte Klassen, die genau eine abstrakte Methode vorschreiben, etwa jva.util.TimerTask. Solche Klassen können nicht über einen Lambda-Ausdruck realisiert werden; hier müssen Entwickler weiterhin zu Klassenimplementierungen greifen, und das kürzeste ist eine innere anonyme Klasse. Eigene Hilfsklassen können natürlich den Code etwas abkürzen, aber eben nur mit eigener Implementierung. Zwei Strategien bieten sich an: durch Delegation oder Vererbung. Nehmen wir das Beispiel für TimerTask und gehen beide Varianten durch:

import java.util.*;

class TimerTaskLambda {

public static TimerTask createTimerTask( Runnable runnable ) {

return new TimerTask() {

@Override public void run() { runnable.run(); }

};

}

public static void main( String[] args ) {

new Timer().schedule( createTimerTask( () -> System.out.println("Hi") ), 500 );

}

}

Oder mit Vererbung:

public class LambdaTimerTask extends TimerTask {

private final Runnable runnable;

public LambdaTimerTask( Runnable runnable ) {

this.runnable = runnable;

}

@Override public void run() { runnable.run(); }

}

Der Aufruf ist dann statt createTimerTask(…) der des Konstruktors:

new Timer().schedule( new LambdaTimerTask( () -> System.out.println("Hi") ), 500 );

Ähnliche Beiträge

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert