1059 votes

:: (deux points) opérateur en Java 8

J'ai été d'explorer la Java 8 source et trouvé cette partie de code très surprenant.

//defined in IntPipeline.java
@Override
public final OptionalInt reduce(IntBinaryOperator op) {
    return evaluate(ReduceOps.makeInt(op));
}

@Override
public final OptionalInt max() {
    return reduce(Math::max); //this is the gotcha line
}

//defined in Math.java
public static int max(int a, int b) {
    return (a >= b) ? a : b;
}

Est - Math::max quelque chose comme une méthode de pointeur? Comment un normal static méthode converties en IntBinaryOperator?

1114voto

isnot2bad Points 7393

Généralement, on pourrait l'appeler l' reduce méthode à l'aide d' Math.max(int, int) comme suit:

reduce(new IntBinaryOperator() {
    int applyAsInt(int left, int right) {
        return Math.max(left, right);
    }
});

Maintenant que nécessite beaucoup de syntaxe pour appeler juste Math.max. C'est là que les expressions lambda entrent en jeu. Depuis Java 8, il est permis de faire la même chose en beaucoup plus court chemin:

reduce( (int left, int right) -> Math.max(left, right) );

Comment cela fonctionne? Le compilateur java "détecte", que vous souhaitez mettre en œuvre une méthode qui accepte les deux ints et renvoie un int. C'est l'équivalent pour les paramètres formels d'une seule et unique méthode de l'interface IntBinaryOperator (le paramètre de méthode reduce vous voulez l'appeler). Ainsi, le compilateur fait le reste pour vous, il a juste suppose que vous voulez mettre en oeuvre IntBinaryOperator.

Mais comme Math.max(int, int) lui-même remplit les conditions de forme de l' IntBinaryOperator, il peut être utilisé directement. Maintenant, java n'a pas de syntaxe qui permet à une méthode même d'être passé comme argument (vous ne pouvez passer des résultats de la méthode, mais jamais les méthodes de lui-même), l' :: syntaxe a été introduite dans Java 8 pour les méthodes de référence:

reduce(Math::max);

Notez que cela sera interprété par le compilateur, pas par la JVM au moment de l'exécution! Bien qu'elle produit différents bytecode pour tous les trois fragments de code, ils sont sémantiquement égaux, de sorte que les deux dernières peuvent être considérées comme des manches (et probablement plus efficace) versions de l' IntBinaryOperator de mise en œuvre ci-dessus!

(Voir aussi la Traduction des Expressions Lambda)

561voto

Jatin Points 8069

:: est appelée Méthode de Référence. Il s'agit d'une référence à une méthode unique. il s'agit d'une méthode existante par son nom.

Petite Explication: Ci-dessous est un exemple d'une référence à une méthode statique:

Class Hey{
     private static double square(double num){
        return Math.pow(num , 2);
    }
}

Function<Double, Double> square = Hey::square;
double ans = square.apply(23d);

square peuvent être passés comme objet de référence et un déclencheur en cas de besoin. En fait, il peut parfaitement être utilisé comme une référence à une méthode normale d'un objet et pas seulement static .

 Class Hey{
     private double square(double num){
        return Math.pow(num , 2);
    }
}

Hey hey = new Hey();
Function<Double, Double> square = hey::square;
double ans = square.apply(23d);

Function ci-dessus est une interface fonctionnelle. Ainsi, pour expliquer pleinement ::, il est important de comprendre Fonctionnelle de l'Interface. Simplement, en Fonction de l'interface est une interface avec une seule méthode abstraite.

Par exemple: Runnable, Callable, ActionListener et si.

Function ci-dessus est une interface fonctionnelle avec une seule méthode apply. Elle prend un argument et produit un résultat. Donc, maintenant de retour à l' ::, techniquement:

Méthode références sont des expressions qui ont le même traitement que les les expressions lambda (c'est à dire, ils nécessitent un type de cible et encoder interface fonctionnelle des cas), mais au lieu de fournir une méthode corps, ils se réfèrent à une méthode existante par nom

En bref: Méthode de Référence se réfère à une méthode de l'interface fonctionnelle, à savoir sa appliqué la méthode (Comme mentionné précédemment, cette méthode est la seule offerte par les interfaces fonctionnelles). Tout comme Function - dessus qui prend une entrée et de sortie, il existe de nombreuses autres interfaces fonctionnelles: Consumer prend en entrée et renvoie aucun résultat.

Consumer<Integer> b1 = System::exit;   // void exit(int status)
Consumer<String[]> b2 = Arrays::sort;  // void sort(Object[] a)
Consumer<String> b3 = MyProgram::main; // void main(String... args)

Parce qu' :: fournit une référence à la méthode d'une interface fonctionnelle, le type de référence peut être n'importe quoi tant qu'il est valide interface fonctionnelle

class Hey{
    private double getRandom(){
        return Math.random();
    }
}

Callable<Double> call = hey::getRandom;
Supplier<Double> call2 = hey::getRandom;
//Supplier is functional interface that takes no argument and gives a result

Ci-dessus getRandom ne prend aucun argument et renvoie un double. hey::getRandom est une abréviation pour l'expression lambda et son type de référence peut être n'importe quelle interface fonctionnelle qui répond aux critères:- ne prendre aucun argument et renvoie un résultat. Callable et Supplier parfaitement le match.

Un autre exemple:

Set<String> set = new HashSet<>();
set.addAll(Arrays.asList("leo","bale","hanks"));
Predicate<String> pred = set::contains;
boolean exists = pred.test("leo");

Prédicat est une interface fonctionnelle dont la méthode fonctionnelle, c'est de tester. Il prend en entrée et retourne un booléen. :: fournit un cadre de référence (Predicate<String>) qui peut être ensuite utilisé pour vérifier de "leo" satisfait le prédicat.

Bottom line: :: fournit une référence à la méthode de la fonctionnelle de l'interface.

Plus sur :: : Méthode de Référence peuvent être obtenus dans des styles différents, mais ils signifient tous la même chose:

  1. Une méthode statique (ClassName::methName)
  2. Une méthode d'instance d'un objet particulier (instanceRef::methName)
  3. Une super méthode d'un objet particulier (super::methName)
  4. Une méthode d'instance de l'arbitraire d'un objet d'un type particulier (ClassName::methName)
  5. Un constructeur de la classe de référence (ClassName::new)
  6. Un tableau constructeur de référence (TypeName[]::new)

À titre de référence: http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html

59voto

user503413 Points 2043

Oui, que la vraie. L' :: opérateur, il est utilisé pour la méthode de référencement. Ainsi, l'on peut extraire statique méthodes de classes en utilisant des méthodes ou des objets. Le même opérateur peut être utilisé même pour les constructeurs. Tous les cas mentionnés ici sont illustrées dans l'exemple de code ci-dessous.

La documentation officielle d'Oracle peuvent être trouvés ici.

Vous pouvez avoir une meilleure vue d'ensemble du JDK 8 changements dans cet article. Dans la Méthode ou le Constructeur de référencement de l'article un exemple de code est également fournie:

interface ConstructorReference {
    T constructor();
}

interface  MethodReference {
   void anotherMethod(String input);
}

public class ConstructorClass {
    String value;

   public ConstructorClass() {
       value = "default";
   }

   public static void method(String input) {
      System.out.println(input);
   }

   public void nextMethod(String input) {
   // operations
   }

   public static void main(String... args) {
   // constructor reference
       ConstructorReference reference = ConstructorClass::new;
       ConstructorClass cc = reference.constructor();

       // static method reference
       MethodReference mr = cc::method;

       // object method reference
       MethodReference mr2 = cc::nextMethod;

       System.out.println(cc.value);
       }
}

28voto

sreenath Points 11

:: est un nouvel opérateur inclus dans java 8, qui est utilisé pour désigner une méthode d'une classe existante. Vous pouvez vous référer méthode statique et non des méthodes statiques de la classe.

pour la référence des méthodes statiques, la syntaxe est ClassName :: methodName , pour la référence non des méthodes statiques, la syntaxe est objRef :: methodName et ClassName :: methodName .

La seule condition pour référence d'une méthode, il existe une méthode d'une interface fonctionnelle qui doit être compatible avec la méthode de référence.

méthode de références lors de l'évaluation crée une instance de l'interface fonctionnelle.

Trouvé sur : http://www.speakingcs.com/2014/08/method-references-in-java-8.html

24voto

david99world Points 7444

C'est une référence à une méthode en Java 8. La documentation oracle est ici.

Comme indiqué dans la documentation...

La méthode de référence de la Personne::compareByAge est une référence à une statique la méthode.

Ce qui suit est un exemple d'une référence à une méthode d'instance d'une objet particulier:

class ComparisonProvider {
    public int compareByName(Person a, Person b) {
        return a.getName().compareTo(b.getName());
    }

    public int compareByAge(Person a, Person b) {
        return a.getBirthday().compareTo(b.getBirthday());
    } } ComparisonProvider myComparisonProvider = new ComparisonProvider(); Arrays.sort(rosterAsArray, myComparisonProvider::compareByName); 

La méthode de référence myComparisonProvider::compareByName appelle la méthode compareByName c'est la partie de l'objet myComparisonProvider. Le JRE en déduit l' méthode type d'arguments, qui sont dans ce cas (Personne, Personne).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X