Comment la méthode apply () fonctionne-t-elle en Java?
Concernant l'interface fonctionnelle d'UnaryOperator, j'ai lu la documentation, elle dit
new Stream().map(new Uppercase())
Représente une opération sur un opérande unique qui produit un résultat du même type que son opérande. Il s'agit d'une spécialisation de Function pour le cas où l'opérande et le résultat sont du même type.
Il s'agit d'une interface fonctionnelle dont la méthode fonctionnelle est Function.apply(Object)
.
Quelle est la méthode fonctionnelle?
J'ai la classe suivante qui implémente l'interface UnaryOperator.
public class Uppercase implements UnaryOperator<String> { @Override public String apply(String s) { return s.trim().toUpperCase(); } }
Dans l'appel de méthode,
@FunctionalInterface public interface UnaryOperator<T> extends Function<T,T>
Il convertit tout flux d'entrée en majuscules. Ma question est la suivante: la méthode apply ()
de la classe Uppercase est-elle appelée automatiquement? (Est-ce comme si la méthode toString ()
est appelée automatiquement par la méthode println ()
?)
Je n'ai trouvé aucun exemple sans appeler apply ()
explicitement. Alors s'il vous plaît, aidez-moi à comprendre ce qui s'est passé ici.
4 Réponses :
La méthode apply () de la classe Uppercase est-elle appelée automatiquement?
La méthode map
implémentée dans Stream
est chargée d'appeler la méthode apply
de la Function
que vous ai créé.
Remarque : Majuscule
implémente UnaryOperator
étend la Function
qui est l'endroit où le La mise en œuvre de apply
que vous avez définie est appelée.
Il convertit tout flux d'entrée en majuscules. Ma question est, est-ce que la méthode apply () de la classe Uppercase est appelée automatiquement?
En effet, c'est le rôle de l'implémentation
Stream.map ()
d'appelerapply ()
dessus, donc vous ne le ferez jamais lorsqueStream.map ()
est appelée.La classe abstraite
ReferencePipeline
fait cela:new Stream().map(s->s.trim().toUpperCase())....
map ( )
défini dans Stream est déclaré comme:<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Stream.map ()
attend uneFunction
et en passant unUnaryOperator
vous fournissez tout ce qui est nécessaire.Je n'ai trouvé aucun exemple sans appeler explicitement la méthode apply (). Alors, aidez-moi à comprendre ce qui s’est passé ici.
En général, vous n'implémentez pas directement l'interface fonctionnelle mais vous passez un lambda car c'est plus simple:
@SuppressWarnings("unchecked") public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) { Objects.requireNonNull(mapper); return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) { return new Sink.ChainedReference<P_OUT, R>(sink) { @Override public void accept(P_OUT u) { downstream.accept(mapper.apply(u)); // <------ HERE } }; } }; }
Oui, c'est exactement comme la fonction toString ()
invoque dans la fonction println ()
. println ()
accepte tous les objets, donc par défaut toString ()
hérite de la classe java.lang.Object
ainsi que de Stream La fonction
accepte les objets de type map ()
de la classe java.util.function.Function
dont vous avez exactement fait l'implémentation avec la classe Uppercase
.
En ce qui concerne les interfaces fonctionnelles, l'interface fonctionnelle n'est pas seulement une interface décorée avec l'annotation @FunctionalInterface
. L'interface fonctionnelle ne peut avoir qu'une seule méthode d'instance. Pourrait avoir de nombreuses méthodes static
et default
cependant. Ces interfaces ont essentiellement été introduites pour fonctionner avec le nouveau type de syntaxe de Java 8 appelé Expressions Lambda . Sinon, ce n'est qu'une interface.
Votre solution implémente comme ceci si vous le souhaitez, créant une classe interne anonyme;
new Stream().map(s -> s.trim().toUpperCase());
Pas besoin de déclarer une classe concrète distincte comme Majuscule
. Avec l'expression lambda, vous pouvez raccourcir le code comme ceci;
new Stream().map(new Function() { @Override public String apply(String s) { return s.trim().toUpperCase(); } });
Ceci est l'utilisation des méthodes fonctionnelles des interfaces fonctionnelles. Cela n'est possible que lorsqu'il n'y a qu'une seule méthode d'instance . Pas besoin d'implémenter une classe séparée comme vous l'avez fait.
En informatique, Apply est une fonction qui applique des fonctions aux arguments.
C'est peut-être nouveau pour Java, mais c'est courant dans la programmation fonctionnelle. L'objet peut être traité comme une fonction qui a la méthode apply. Ainsi, lorsqu'un nouvel objet est créé, la méthode apply sera exécutée avec les arguments passés.
La réponse de Vlad Gudim a été détaillée: https://stackoverflow.com/a/9738862/3812323 < / p>
C'est pour la scala, mais c'est vrai dans le paradigme fonctionnel.
Avez-vous utilisé votre moteur de recherche préféré pour rechercher interface fonctionnelle java et lu l’une des excellentes descriptions de son fonctionnement? On s'attend à ce qu'avant de poser une question fondamentale comme celle-ci, vous ayez fait quelques recherches.
il vaut également la peine de consulter la documentation avec laquelle presque chaque classe / interface est fournie: FunctionalInterface et la spécification du langage Java: JLS §9.8