5
votes

Exemple concret d'utilisation d'une interface fonctionnelle en Java

Je sais qu'une interface fonctionnelle signifie que vous pouvez avoir exactement / seulement 1 méthode abstraite avec plus de 1 méthode (s) par défaut, mais je me demande comment la relier à un exemple / situation du monde réel d'utilisation d'une interface fonctionnelle dans Java.

Pourriez-vous donner une situation / un exemple valide?

Merci d'avance!


1 commentaires

Lambda sont des implémentations de l'interface fonctionnelle ... donc implicitement (par un compilateur ou au moment de l'exécution) ou explicitement (par code ... affectation) elles vont être utilisées. Un exemple pratique est une utilisation de prédicat dans le code pour le filtrage.


5 Réponses :


1
votes

Les interfaces marquées avec FunctionalInterface sont garanties applicables dans les contextes où une expression lambda avec le paramètre et les types de retour appropriés est attendue. En plus de cela, ils n'ont aucun usage. Il peut y avoir des optimisations, mais dans tous les cas cela n'a pas d'importance


0 commentaires

3
votes

L'une des principales utilisations qu'ils ont fournies est que les instances d'interfaces fonctionnelles peuvent être créées avec des expressions lambda et des références de méthode ainsi que l'utilisation d'un constructeur en même temps. Par exemple, une interface fonctionnelle Sample définie comme:

 // Assignment context
 Predicate<String> p = String::isEmpty;

 // Method invocation context
 stream.filter(e -> e.getSize() > 10)...

 // Cast context
 stream.map((ToIntFunction) e -> e.getSize())...

peut être instanciée en une simple ligne de code comme:

sample.ab();

et ensuite appelé le cas échéant comme:

Sample sample = () -> System.out.println("ab called");

Je citerais en outre le Javadoc à partir de java.util .function package:

Les interfaces fonctionnelles peuvent fournir un type de cible dans plusieurs contextes, comme contexte d'affectation , appel de méthode ou contexte de conversion :

@FunctionalInterface
public interface Sample {
    void ab();
}

De plus, ces interfaces pourraient être annotées avec @FunctionalInterface annotation.

Cette annotation n'est pas obligatoire pour que le compilateur reconnaisse une interface comme interface fonctionnelle, mais simplement une aide à la capture l'intention de conception et demandez l'aide du compilateur pour identifier violations accidentelles de l'intention de conception.

Également un point intéressant pour utiliser les concepts avec de telles interfaces existantes,

le compilateur traitera toute interface répondant à la définition d'une interface fonctionnelle comme une interface fonctionnelle, qu'elle soit ou pas une annotation FunctionalInterface est présente sur la déclaration d'interface.


0 commentaires

6
votes

Tout d'abord, l'annotation @FunctionalInterface est utilisée par les interfaces fonctionnelles intégrées de Java Predicate , Function , Consumer code >, etc ...

D'un autre côté, vous pouvez créer votre personnalisé comme suit:

doSomething(someValue, this::customConsumerMethodThrowingAnException);

Ensuite, vous pouvez l'utiliser comme paramètre de méthode:

public <T, R> void doSomething(T value, ThrowingConsumer<T, R> consumer) {
    // ...
}

Et puis appelez-le comme ceci:

@FunctionalInterface
public interface ThrowingConsumer<T> {
    void accept(T t) throws CustomException;
}

Il vaut la peine de mentionner que @ FunctionalInterface n'est pas obligatoire. Le compilateur conviendra parfaitement à toute interface de réunion les exigences .

Le compilateur le traite d'une manière similaire à celle de l'annotation @Override . Le code se compile même sans lui. Mais une fois ajouté, il rend le code plus clair et plus sûr pour ceux qui le maintiendront à l'avenir.


1 commentaires

Pourriez-vous ajouter un commentaire sur le fait que @FunctionalInterface n'est pas nécessaire, mais uniquement présent pour empêcher les SMI utilisant un lambdas d'avoir des méthodes ajoutées, brisant ainsi la compatibilité de l'interface. Sinon, cette réponse concerne uniquement les SMI - pas @FunctionalInterface ...



3
votes

Nous avons toujours eu des interfaces fonctionnelles avant JDK8 mais pas de lambdas, de références de méthode, etc.

A partir de JDK8, ils fournissent un type de cible pour les expressions lambda, les références de méthodes et à leur tour, ont une meilleure lisibilité et un code plus compact.

Exemple, avant Java-8, si vous vouliez fournir une logique qui sera exécutée à chaque fois qu'un composant Button est cliqué, vous feriez:

btn.setOnAction(event -> System.out.println("Hello World!"));

C'est encombrant, difficile à lire et pas assez compact. car EventHandler est par définition une interface fonctionnelle c'est à dire qu'il a un SAM à partir de jdk8 vous pouvez maintenant faire:

 btn.setOnAction(new EventHandler<ActionEvent>() { 
       @Override
       public void handle(ActionEvent event) {
            System.out.println("Hello World!");
       }
 });

Vous ne voyez que la partie du code qui vous intéresse, c'est-à-dire la logique à exécuter lorsque le bouton est cliqué.

De plus, en raison du fait que nous pouvons utiliser des interfaces fonctionnelles comme types de cibles pour les expressions et méthodes lambda références, cela serait utile lorsque:

  • en passant un comparateur à une méthode de tri, par exemple List.sort , Stream.sorted , Collections.sort etc.
  • en passant un bloc de code pour exécuter une tâche dans un thread séparé

etc...

tout en gardant le code lisible, compact et concis.

Les interfaces fonctionnelles sont largement utilisées dans l'API Java-stream.

Il n'y a aucune raison pour vous de créer votre propre interface fonctionnelle sauf qu'il n'y en a pas une qui réponde à vos exigences de java.util.function ou que le nom de l'interface fonctionnelle n'est pas aussi lisible vous pouvez donc créer la vôtre.


Il y a aussi une annotation @FunctionalInterface recommandée mais non requise chaque fois que vous créez une interface fonctionnelle (la bibliothèque standard utilise beaucoup cela).

Cela permet au compilateur de vérifier que l'entité annotée est une interface avec une seule méthode abstraite, sinon donne une erreur.

Ceci est également très utile pour être capable d'attraper des erreurs lors de la refactorisation de votre code.


0 commentaires

1
votes

Les lambdas sont des implémentations de l'interface fonctionnelle ... donc implicitement (par un compilateur ou au moment de l'exécution) ou explicitement (par affectation de code ...) ils vont être utilisés. Un exemple pratique est

  1. Prédicat: utilisation dans le code pour le filtrage.
  2. Fonctions: Map.computeIfAbsent ("xxx", s -> s.length ());
  3. BiFunction: salaires.replaceAll ((name, oldValue) -> name.equals ("Freddy")? oldValue: oldValue + 10000);
  4. Consommateurs: List.forEach (nom -> System.out.println ("Bonjour," + nom));

0 commentaires