Ce qui est le plus proche pour remplacer un pointeur de fonction en Java?
J'ai une méthode qui est d'environ une dizaine de lignes de code. Je veux créer plus de méthodes qui font exactement la même chose, sauf pour un petit calcul qui va changer une ligne de code. C'est une application parfaite pour passer un pointeur de fonction pour remplacer qu'une seule ligne, mais Java n'a pas de pointeurs de fonction. Quelle est ma meilleure alternative?
- Java 8 aura le Expressions Lambda. Vous pouvez en lire plus sur les expressions lambda, ici.
- Je n'ai pas tout à fait penser à des expressions lambda comptent comme des pointeurs de fonction. Le
::
opérateur, sur l'autre main... - Désolé pour la fin du commentaire 😉 - normalement, vous n'avez pas besoin d'un pointeur de fonction pour cela. Il suffit d'utiliser un modèle de méthode! (en.wikipedia.org/wiki/Template_method_pattern)
- en regardant l'article, semble exagéré - plus complexe que les réponses données ici. Plus précisément, le modèle de la méthode nécessite la création d'une sous-classe pour chaque alternative de calcul. Je ne vois pas l'OP d'avoir dit quelque chose qui exige que les sous-classes; il veut simplement créer plusieurs méthodes, et de partager plus de la mise en œuvre. Comme la accepté de répondre à des spectacles, c'est facile à faire "à la place" (à l'intérieur de chaque méthode), avant même de Java 8 avec son lambdas.
- La solution retenue exige également de la classe par le calcul (même si c'est juste un anonyme intérieur de la classe). Et la méthode de modèle de modèle peut aussi être réalisé en utilisant les classes internes anonymes, de sorte qu'il ne diffère pas beaucoup de la solution retenue concernant les frais généraux (avant Java 8). Il est donc plus une question de l'utilisation modèle et détaillés exigences, dont nous ne connaissons pas. J'apprécie la accepté de répondre et je voulais juste ajouter une autre possibilité de penser.
- Avec l'ajout de la
::
opérateur il y a quelques années, vous souhaitez peut-être envisager d'accepter un up-to-date de la réponse (par exemple, Alex, akhil_mittal de l', user3002379 de l', ou de mine).
Vous devez vous connecter pour publier un commentaire.
Anonyme intérieur de la classe
Dites que vous voulez avoir une fonction passés avec un
String
param qui renvoie unint
.Vous devez d'abord définir une interface avec la fonction en tant que seul membre, si vous ne pouvez pas réutiliser un existant.
Une méthode qui prend le pointeur voudrais juste accepter
StringFunction
exemple comme ceci:Et appelé de la sorte:
EDIT: Dans Java 8, vous pouvez l'appeler avec une expression lambda:
Default methods are allowed only at source level 1.8 or above
etLambda expressions are allowed only at source level 1.8 or above
. Avez-vous un Java 7 compatible version disponible?Pour chaque "pointeur de fonction", j'aimerais créer un petit foncteur de classe qui implémente le calcul.
Définir une interface que toutes les classes se mettre en œuvre, et de passer des instances de ces objets dans votre plus grande fonction. C'est une combinaison de la "modèle de commande", et "modèle de stratégie".
@sblundy l'exemple est bon.
Quand il y a un nombre prédéfini de différents calculs que vous pouvez faire dans cette ligne, à l'aide d'un enum est un rapide, mais de façon claire afin de mettre en œuvre un modèle de stratégie.
De toute évidence, la stratégie de la déclaration de la méthode, ainsi que exactement une instance de chaque mise en œuvre sont tous définis dans une classe unique/fichier.
Vous avez besoin pour créer une interface qui fournit la fonction(s) que vous souhaitez passer. par exemple:
Puis, quand vous en avez besoin pour passer d'une fonction, vous pouvez implémenter cette interface:
Enfin, la fonction map utilise le passé dans Fonction1 comme suit:
Vous pouvez souvent utiliser Exécutable au lieu de votre propre interface si vous n'avez pas besoin de passer des paramètres, ou vous pouvez utiliser diverses autres techniques pour faire les param comptent moins "fixe", mais il est généralement un compromis avec la sécurité de type. (Ou vous pouvez surcharger le constructeur de votre fonction de l'objet à transmettre dans les params de cette façon.. il y a beaucoup d'approches, et certains fonctionnent mieux dans certaines circonstances.)
Méthode des références à l'aide de la
::
opérateurVous pouvez utiliser la méthode références de la méthode des arguments où la méthode accepte un interface fonctionnelle. Une interface fonctionnelle est une interface qui contient une seule méthode abstraite. (Une interface fonctionnelle peut contenir une ou plusieurs méthodes par défaut ou méthodes statiques.)
IntBinaryOperator
est une interface fonctionnelle. Sa méthode abstraite,applyAsInt
, accepte deuxint
s, ainsi que ses paramètres et renvoie unint
.Math.max
accepte également les deuxint
s et renvoie unint
. Dans cet exemple,A.method(Math::max);
faitparameter.applyAsInt
envoyer ses deux valeurs d'entrée pourMath.max
et de retourner le résultat de cetteMath.max
.En général, vous pouvez utiliser:
au lieu de:
qui est l'abréviation de:
Pour plus d'informations, voir :: (deux points) opérateur en Java 8 et Java Langage De Spécification §15.13.
Vous pouvez également le faire (ce qui, dans certains RARE occasions de sens). Le problème (et c'est un gros problème) c'est que vous perdez tous les typesafety de l'utilisation d'une classe ou interface et vous avez à traiter le cas où la méthode n'existe pas.
Il a l ' "avantage" que vous pouvez ignorer les restrictions d'accès et d'appeler les méthodes privées (non illustré dans l'exemple, mais vous pouvez appeler les méthodes que le compilateur ne serait pas normalement vous permettre d'appeler).
Encore une fois, c'est un cas rare que cela fait sens, mais à ces occasions, c'est un bel outil pour.
Si vous avez juste une ligne qui est différente, vous pourriez ajouter un paramètre comme un drapeau et d'un si(drapeau) déclaration qui appelle une ligne ou l'autre.
Vous pouvez aussi être intéressé à entendre parler des travaux en cours pour Java 7 impliquant fermetures:
Quel est l'état actuel de fermetures en Java?
http://gafter.blogspot.com/2006/08/closures-for-java.html
http://tech.puredanger.com/java7/#closures
Java 8 Interfaces Fonctionnelles et Méthode des Références à l'aide de la
::
opérateur.Java 8 est en mesure de maintenir la méthode de référence ( MyClass::nouvelle ) avec "@ Interface Fonctionnelle" pointeurs. Il n'y a pas besoin pour le même nom de méthode, seulement même méthode de signature est nécessaire.
Exemple:
Donc, ce que nous avons ici?
VOUS DEVEZ UTILISER DES INTERFACES FONCTIONNELLES POUR LES AUDITEURS, ET UNIQUEMENT POUR ÇA!
Parce que tous les autres pointeurs de fonction sont vraiment mauvais pour la lisibilité du code et de la capacité à comprendre. Cependant, la méthode directe de références, parfois, viennent à portée de main, avec foreach par exemple.
Il y a plusieurs prédéfinis Interfaces Fonctionnelles:
Pour d'anciennes versions de Java, vous devriez essayer de Goyave Bibliothèques, qui a les mêmes fonctionnalités, et de la syntaxe, comme Adrian Petrescu a mentionné ci-dessus.
Pour la recherche de regarder Java 8 Triche
et merci pour Le Gars avec Le Chapeau pour le Java Langage De Spécification §15.13 lien.
@sblundy la réponse est grande, mais les classes internes anonymes ont deux petits défauts, le principal étant qu'ils ont tendance à ne pas être réutilisable et le secondaire est un volumineux syntaxe.
La bonne chose est que son modèle se développe en pleine classes sans aucun changement dans la classe principale (celle d'effectuer les calculs).
Lorsque vous instanciez une nouvelle classe, vous pouvez passer des paramètres dans cette classe qui peuvent agir comme des constantes dans votre équation--donc, si l'un de vos classes internes ressembler à ceci:
mais parfois vous avez besoin d'un:
et peut-être un tiers de ce qui est:
plutôt que de faire deux anonymes intérieur des classes ou de l'ajout d'un "passthrough" paramètre, vous pouvez faire une seule classe RÉELLE que vous instanciez comme:
Il serait tout simplement stocker la constante dans la classe et de l'utiliser dans la méthode spécifiée dans l'interface.
En fait, si vous SAVEZ que votre fonction ne seront pas enregistrées et/ou réutilisés, vous pourriez faire ceci:
Mais immuable classes sont plus en sécurité, je ne peux pas venir avec une justification pour faire une classe comme ça mutable.
J'ai poster ce parce que je grince des dents chaque fois que j'entends anonyme intérieure--j'ai vu beaucoup de code redondant qui était "Nécessaire" parce que la première chose que le programmeur n'était d'aller anonymes quand il aurait utilisé une classe réelle et jamais repensé sa décision.
Google Goyave bibliothèques, qui sont en train de devenir très populaire, ont un générique La fonction et Prédicat objet qu'ils ont travaillé dans de nombreuses parties de leur API.
Sonne comme un modèle de stratégie pour moi. Découvrez fluffycat.com Java modèles.
L'une des choses que j'ai vraiment manquer lors de la programmation en Java est fonction de rappels. Un exemple de situation où la nécessité pour ces gardé présenter elle-même était dans récursivement le traitement des hiérarchies où vous souhaitez effectuer des mesures précises pour chaque élément. Comme marcher sur une arborescence de répertoire, ou de la transformation d'une structure de données. Le minimaliste à l'intérieur de moi déteste avoir à définir une interface, puis une mise en œuvre pour chaque cas spécifique.
Un jour, je me demandais pourquoi pas? Nous avons pointeurs de méthode - la Méthode de l'objet. Avec l'optimisation des compilateurs JIT, réfléchissant à l'invocation n'a vraiment pas de réaliser un gain de performance énorme peine plus. Et d'ailleurs, à côté de, disons, la copie d'un fichier d'un emplacement à un autre, le coût de l'expression de l'invocation de méthode bien pâle dans l'insignifiance.
Comme je le pensais plus à ce sujet, j'ai réalisé qu'un rappel dans le paradigme de la programmation orientée objet nécessite une liaison d'un objet et une méthode d'ensemble - entrez l'objet de Rappel.
Découvrez ma réflexion à partir de la solution pour Rappels en Java. Gratuit pour toute utilisation.
oK, ce fil est déjà assez vieux, donc très probablement ma réponse n'est pas utile pour la question. Mais depuis ce thread m'a aidé à trouver ma solution, je vais le mettre ici de toute façon.
J'avais besoin d'utiliser une variable statique méthode connue d'entrée et de sortie connus (les deux double). Alors, sachant que la méthode de package et le nom, je pourrais travailler comme suit:
pour une fonction qui accepte un double comme un paramètre.
Donc, dans ma situation concrète, j'ai initialisé avec
et invoquée plus tard dans une situation plus complexe avec
où l'activité est l'arbitraire d'un double de la valeur. Je pense peut-être faire un peu plus abstrait et de généraliser, comme SoftwareMonkey a fait, mais pour l'instant je suis assez heureux avec la façon dont il est. Trois lignes de code, pas de classes et interfaces nécessaires, qui n'est pas trop mauvais.
code
markdown, j'ai été trop impatient et stupide de le trouver;-)De faire la même chose sans interfaces pour une multitude de fonctions:
Découvrez lambdaj
http://code.google.com/p/lambdaj/
et en particulier la nouvelle de la fermeture de la fonctionnalité
http://code.google.com/p/lambdaj/wiki/Closures
et vous trouverez une très lisible pour définir la fermeture ou de pointeur de fonction sans créer de sens de l'interface ou de l'utilisation laid intérieure classes
Wow, pourquoi ne pas simplement créer un Délégué de classe qui n'est pas si difficile étant donné que je l'ai déjà fait pour java et de l'utiliser pour passer en paramètre (où T est le type de retour. Je suis désolé, mais en tant que C++/C#, programmeur en général l'apprentissage de java, j'ai besoin de pointeurs de fonction parce qu'ils sont très pratique. Si vous êtes familier avec n'importe quelle classe qui traite de la Méthode d'Informations, vous pouvez le faire. Dans les bibliothèques java, qui serait celle de java.lang.de réfléchir.méthode.
Si vous utilisez toujours une interface, vous avez toujours à le mettre en œuvre. Dans eventhandling il n'y a vraiment pas de meilleure façon autour de l'inscription/désinscription de la liste de gestionnaires mais pour les délégués où vous devez passer dans les fonctions et non pas le type de la valeur, en faisant un délégué de classe pour gérer cela pour le surclasse une interface.
Aucun de Java 8 réponses ont donné une complète, cohérente exemple, donc la voici.
Déclarer la méthode qui accepte le "pointeur de fonction", comme suit:
Appel en fournissant la fonction avec une expression lambda:
Si quelqu'un a de la difficulté à passer d'une fonction qui prend un ensemble de paramètres afin de définir son comportement, mais d'un autre ensemble de paramètres sur lequel exécuter, à l'instar du Régime:
voir Passer de la Fonction avec le Paramètre-Comportement Défini en Java
Depuis Java8, vous pouvez utiliser les lambdas, qui ont également des bibliothèques dans l'officiel SE 8 de l'API.
Utilisation:
Vous devez utiliser une interface avec une seule méthode abstraite.
Créer une instance de celui-ci (vous pouvez utiliser l'un de java SE 8 déjà fourni) comme ceci:
Pour plus d'informations caisse de la documentation: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
Avant Java 8, plus proche de substitution de la fonction pointeur de fonctions de type a une classe anonyme. Par exemple:
Mais maintenant dans Java 8, nous avons une très soigné alternative connu comme expression lambda, qui peut être utilisé comme:
où isBiggerThan est une méthode
CustomClass
. Nous pouvons également utiliser la méthode des références ici: