J'ai une méthode privée générique qui effectue des tâches courantes et est utilisée par d'autres méthodes. La méthode générique a des conditions if
et else
pour prendre en charge d'autres méthodes appelées. Exemple:
private void myGenericMethod(String name, int age){
common task1;
common task2;
if(name!= null && name.length > 0){
specific task 1;
specific task 2;
} else{
specific task 3;
specific task 4;
}
if(age > 18){
specific task 1`;
specific task 2`;
}
}
Je veux utiliser Java 8 lambda et j'ai créé une interface fonctionnelle appelée Invoker
avec une méthode invoke
.
public interface Invoker{
public void invoke()
}
Maintenant, ma méthode générique ressemble à ceci et la méthode publique gère correctement le rappel de la fonction invoke:
private void myGenericMethod(Invoker invoker){
common task1;
common task2;
invoker.invoke();
}
Y a-t-il une interface fonctionnelle dans le JDK que je peux utiliser au lieu de créer cette interface par moi-même?
Package Java.util.function
ne contient pas d'interface fonctionnelle avec une méthode qui ne nécessite aucun paramètre et renvoie void
. Mais vous pouvez utiliser l'interface Runnable
à la place.
private void myGenericMethod(Runnable runnable){
common task1;
common task2;
//consider checking if runnable != null to avoid NPE
runnable.run();
}
L'invocation serait alors assez simple:
myGenericMethod(() -> {
//do something fancy
System.out.println("Hello, world!");
});
Il existe d'autres interfaces fonctionnelles qui pourraient vous intéresser, par exemple:
Supplier<T>
si vous souhaitez renvoyer une valeur de T
sans passer aucun paramètreFunction<T,R>
si vous voulez passer une valeur de T
et renvoyer une valeur de R
Consumer<T>
si vous voulez passer la valeur T
comme paramètre et retourner void
Runnable
?L'utilisation de l'interface Runnable
pour un lambda qui ne retourne rien et n'attend aucun paramètre peut sembler controversée pour de nombreux programmeurs. Runnable
a été inventé pour exécuter un code dans un thread séparé et de nombreux programmeurs identifient cette classe avec le multithreading. Même documentation dit:
L'interface
Runnable
doit être implémentée par n'importe quelle classe dont les instances sont destinées à être exécutées par un thread.
Quelqu'un déjà posé une question similaire il y a 2 ans et si vous regardez ce commentaire et la réaction de Brian Goetz à cela, vous comprendrez que Java ont conclu qu'il n'était pas nécessaire de créer une autre interface fonctionnelle qui imite l'implémentation de l'interface Runnable
.
Il y a aussi la possibilité d'utiliser Consumer<Void>
. Cela pourrait ressembler à ceci
public void init(Consumer<Void> callback) {
callback.accept(null);
}
init((Void) -> done());
Je suggère d'utiliser Consumer comme interface de rappel. En le comparant au langage JavaScript, les rappels sont liés avec une étendue. Par conséquent, si vous utilisez l'interface Consumer, vous pouvez transmettre la portée en tant que paramètre à la fonction. Ex:
public void startTracer(String tracerName, Event boundEvent) {
executeOnTracer(tracer -> tracer.startTracer(tracerName, boundEvent));
}
...
private void executeOnTracer(Consumer<Tracer> callback) {
TracerController tracer = null;
if (isTracerActive()) {
tracer = getTracer();
}
Optional.ofNullable(tracer).ifPresent(callback::accept);
}