2014-03-13 8 views
19

Wie Sie hoffentlich wissen, können Sie in Java 8 lambdas verwenden, um beispielsweise anonyme Methoden zu ersetzen.Wie TimerTask mit Lambdas zu verwenden?

Ein Beispiel kann 8 hier von Java 7 vs Java zu sehen:

Runnable runnable =() -> checkDirectory(); 

oder

Runnable runnable = this::checkDirectory; 
:

Runnable runnable = new Runnable() { 
    @Override 
    public void run() { 
     checkDirectory(); 
    } 
}; 

können, da beide die folgenden Möglichkeiten in Java 8 ausgedrückt werden

Dies ist, weil Runnable eine funktionale Schnittstelle ist, mit nur einem (abstrakten) öffentlichen Nicht-Standard-me thod.

jedoch ... Für TimerTask haben wir folgendes:

TimerTask timerTask = new TimerTask() { 
    @Override 
    public void run() { 
     checkDirectory(); 
    } 
}; 

kommt mir bekannt vor, nicht wahr?
Die Verwendung eines Lambda-Ausdrucks funktioniert jedoch nicht, da TimerTask eine abstrakte Klasse ist, obwohl es nur eine abstrakte nicht standardmäßige öffentliche Methode gibt, keine Schnittstelle und daher auch keine funktionale Schnittstelle.
Es ist auch nicht in eine Schnittstelle mit Standardimplementierungen umgestaltet, weil es Zustand trägt, so dass es dann nicht getan werden kann.

Also meine Frage: Gibt es eine Möglichkeit, Lambdas beim Aufbau der TimerTask zu verwenden?

Was ich wollte, ist folgendes:

Timer timer = new Timer(); 
timer.schedule(this::checkDirectory, 0, 1 * 1000); 

Statt einige hässliche anonyme innere Klasse, ist es eine Möglichkeit, es schöner zu machen?

+7

Da Sie moderne Funktionen zu verwenden, warum nicht den ganzen Weg und verwende einen 'ScheduledExecutorService' anstelle einer' TimerTask'? ;) – fge

+0

@fge Nun, ich wusste nicht, dass es existiert, bis jetzt ... Jetzt denke ich darüber nach, hat Java ihre APIs nicht erwähnen, dass es eine neuere ähnliche Funktion gibt, wenn das alte Feature noch nicht * ist veraltet *? – skiwi

+0

Im Fall von 'Timer' rät Josh Bloch's Effektive Java 2nd Edition. Es ist jedoch keine offizielle Position der JDK-API. –

Antwort

10

Anbetracht dessen, dass zuerst Timer ist effektiv eine veraltete API, aber Ihre Frage unterhaltsam dennoch könnten Sie einen kleinen Wrapper um es schreiben, die die schedule Verfahren anpassen würde eine Runnable, und auf der Innenseite zu akzeptieren, würden Sie drehen, dass Runnable in a TimerTask. Dann hätten Sie Ihre schedule Methode, die ein Lambda akzeptieren würde.

public class MyTimer { 
    private final Timer t = new Timer(); 

    public TimerTask schedule(final Runnable r, long delay) { 
    final TimerTask task = new TimerTask() { public void run() { r.run(); }}; 
    t.schedule(task, delay); 
    return task; 
    } 
} 
+9

Technisch ist Ihre Antwort korrekt, allerdings werde ich persönlich mit 'ScheduledExecutorService' anstelle von' TimerTask' gehen. – skiwi

+1

Und eine sehr gute Wahl :) –

+1

Was ist die aktuelle API dann? – krivar

0

Um Marko Topolnik der Vervollständigung Antwort über Timer, Sie haben nur schedule Methode mit einem Lambda nennen.

schedule(() -> { 
    System.out.println("Task #1 is running"); 
}, 500); 
+0

'Runnable' ist eine Schnittstelle, die Sie mit einem Lambda implementieren können. Sie können also die Methode 'schedule' mit einem Lambda aufrufen. Hier ist ein Arbeitsgedächtnis https://gist.github.com/fsamin/ec5aa79bc23965eca277 –

+1

Missverstandene Antwort; Du hast natürlich vollkommen recht. – gerardw

-1

Sie können auch einen Timer leicht mit Lambda-Ausdrücke aus dem Swing-API erstellen, wenn Sie wollen (aber nicht mit Timertask):

new javax.swing.Timer(1000, (ae) -> this::checkDirectory).start();