Disons que j'ai l'interface fonctionnelle suivante en Java 8:
interface Action<T, U> {
U execute(T t);
}
Et dans certains cas, j'ai besoin d'une action sans arguments ni type de retour. Alors j'écris quelque chose comme ça:
Action<Void, Void> a = () -> { System.out.println("Do nothing!"); };
Cependant, cela me donne une erreur de compilation, je dois l'écrire comme
Action<Void, Void> a = (Void v) -> { System.out.println("Do nothing!"); return null;};
Ce qui est moche. Existe-t-il un moyen de se débarrasser du Void
paramètre de type?
Runnable
, que vous recherchezRunnable r = () -> System.out.println("Do nothing!");
Réponses:
La syntaxe que vous recherchez est possible avec une petite fonction d'aide qui convertit un
Runnable
enAction<Void, Void>
(vous pouvez le placerAction
par exemple):la source
@FunctionalInterface
. Il dit simplement qu'il n'est pas possible de l'étendre ...Runnable
action devrait prendre un@FunctionalInterface
quelque chose de personnalisé appeléSideEffect
, 2. le besoin d'une telle fonction d'aide met en évidence que quelque chose de bizarre se passe et probablement l'abstraction est brisée.À utiliser
Supplier
si cela ne prend rien, mais renvoie quelque chose.À utiliser
Consumer
si cela prend quelque chose, mais ne renvoie rien.À utiliser
Callable
si elle renvoie un résultat et peut lancer (la plupart s'apparenteThunk
en termes généraux de CS).À utiliser
Runnable
s'il ne fait ni l'un ni l'autre et ne peut pas lancer.la source
public static void wrapCall(Runnable r) { r.run(); }
. MerciLe lambda:
représente en fait une implémentation pour une interface comme:
qui est complètement différent de celui que vous avez défini. C'est pourquoi vous obtenez une erreur.
Puisque vous ne pouvez pas étendre votre
@FunctionalInterface
, ni en introduire un nouveau, je pense que vous n'avez pas beaucoup d'options.Optional<T>
Cependant, vous pouvez utiliser les interfaces pour indiquer que certaines des valeurs (type de retour ou paramètre de méthode) sont manquantes. Cependant, cela ne rendra pas le corps lambda plus simple.la source
Something
fonction ne peut pas être un sous-type de monAction
type et que je ne peux pas avoir deux types différents.Vous pouvez créer une sous-interface pour ce cas particulier:
Il utilise une méthode par défaut pour remplacer la méthode paramétrée héritée
Void execute(Void)
, déléguant l'appel à la méthode la plus simplevoid execute()
.Le résultat est qu'il est beaucoup plus simple à utiliser:
la source
Action<T, U>
est déclaré dans la question .....Je pense que ce tableau est court et utile:
Comme indiqué dans les autres réponses, l'option appropriée pour ce problème est un
Runnable
la source
Ce n'est pas possible. Une fonction qui a un type de retour non void (même si c'est
Void
) doit renvoyer une valeur. Cependant, vous pouvez ajouter des méthodes statiquesAction
qui vous permettent de "créer" unAction
:Cela vous permettrait d'écrire ce qui suit:
la source
Ajoutez une méthode statique dans votre interface fonctionnelle
Production
la source
Je ne pense pas que ce soit possible, car les définitions de fonction ne correspondent pas à votre exemple.
Votre expression lambda est évaluée exactement comme
alors que votre déclaration ressemble à
à titre d'exemple, si vous avez l'interface suivante
le seul type de fonction (lors de l'instanciation) qui sera compatible ressemble à
et l'absence de déclaration ou d'argument de retour vous donnera une erreur de compilation.
Par conséquent, si vous déclarez une fonction qui prend un argument et en renvoie un, je pense qu'il est impossible de la convertir en fonction qui ne fait ni l'un ni l'autre des mentionnés ci-dessus.
la source
Juste pour référence, quelle interface fonctionnelle peut être utilisée pour la référence de méthode dans les cas où la méthode lève et / ou renvoie une valeur.
la source