44 votes

Pourquoi cette affectation de référence de méthode compile-t-elle ?

J'ai du mal à comprendre pourquoi le code suivant se compile :

public class MethodRefs {

    public static void main(String[] args) {
        Function<MethodRefs, String> f;

        f = MethodRefs::getValueStatic;

        f = MethodRefs::getValue;
    }

    public static String getValueStatic(MethodRefs smt) {
        return smt.getValue();
    }

    public String getValue() {
        return "4";
    }

}

Je peux voir pourquoi la première affectation est valable - getValueStatic correspond manifestement au Function (il accepte un MethodRefs et renvoie un String ), mais la seconde me laisse perplexe - le getValue n'accepte aucun argument, alors pourquoi est-il toujours valable de l'assigner à la méthode f ?

50voto

Peter Lawrey Points 229686

Le deuxième

f = MethodRefs::getValue;

est la même chose que

f = (MethodRefs m) -> m.getValue();

Pour les méthodes non statiques, il y a toujours un argument implicite qui est représenté comme suit this dans l'appelant.

REMARQUE : L'implémentation est légèrement différente au niveau du code d'octet mais elle fait la même chose.

9voto

Wyzard Points 16284

Une méthode non statique prend essentiellement son this comme un type particulier d'argument. Normalement, cet argument est écrit d'une manière particulière (avant le nom de la méthode, au lieu d'être entre parenthèses après celui-ci), mais le concept est le même. Le site getValue La méthode prend un MethodRefs (son this ) et renvoie une chaîne de caractères, ce qui est compatible avec la fonction Function<MethodRefs, String> interface.

9voto

Andreas Points 3565

Etoffons un peu le tout :

import java.util.function.Function;

public class MethodRefs {

  public static void main(String[] args) {
    Function<MethodRefs, String> f;

    final MethodRefs ref = new MethodRefs();

    f = MethodRefs::getValueStatic;
    f.apply(ref);
    //is equivalent to 
    MethodRefs.getValueStatic(ref);

    f = MethodRefs::getValue;
    f.apply(ref);
    //is now equivalent to 
    ref.getValue();
  }

  public static String getValueStatic(MethodRefs smt) {
    return smt.getValue();
  }

  public String getValue() {
    return "4";
  }
}

6voto

Dans le tutoriel Java, il est expliqué qu'il existe 4 types différents de références de méthodes :

  1. référence à une méthode statique
  2. référence à une méthode d'instance d'un objet particulier
  3. référence à une méthode d'instance d'un objet arbitraire d'un type particulier
  4. référence à un constructeur

Votre cas est le n°3, ce qui signifie que lorsque vous avez une instance de MethodRef c'est-à-dire ref en appelant apply sur votre fonction f sera équivalent à String s = ref.getValue() .

5voto

Carcigenicate Points 16496

Pour les méthodes non statiques, le type de this est considéré implicitement comme le premier type d'argument. Puisqu'il est de type MethodRefs les types se vérifient.

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