web-dev-qa-db-fra.com

Sonar: remplacez ce lambda par une référence de méthode

Cet exemple de code

Collection<Number> values = transform(
        getValuatedObjects(),
        input -> getValueProvider().apply(input).getValue());

viole la règle sonarqube :

Remplacer les lambdas par des références de méthode lorsque cela est possible

est-ce un bug sonar? ou puis-je vraiment utiliser une référence de méthode?

18
gontard

Vous ne pouvez pas remplacer la lambda input -> getValueProvider().apply(input).getValue() par une référence de méthode sans modifier la sémantique.

Une référence de méthode remplace un appel de méthode nique, donc elle ne peut pas simplement remplacer une expression lambda composée de plusieurs appels de méthode.

Une expression lambda de la forme input -> getValueProvider().apply(input) pourrait être remplacée par getValueProvider()::apply si et seulement si le temps d'évaluation de getValueProvider() n'a pas d'importance car dans la forme lambda la est invoquée à chaque évaluation de corps lambda tandis que pour la référence de méthode, elle n'est invoquée qu'une seule fois et le résultat est capturé.

Ceci est similaire à la différence entre x -> System.out.println(x) et System.out::println Où la lecture du contenu du champ System.out Se produit à des moments différents mais généralement cela n'a pas d'importance. Mais vous devez être conscient de la différence.

Dans votre exemple, une troisième méthode getValue() est invoquée. La seule façon d'exprimer cela avec des références de méthode nécessite une interface fonctionnelle comme Function qui a des méthodes comme andThen et/ou compose. Cependant, la façon dont Java 8 fonctionne, cela nécessiterait de transtyper la première référence de méthode à l'interface cible pour invoquer la méthode de combinaison qui ne serait en aucun cas plus facile à lire que l'expression lambda que vous avez maintenant: ((Function<X,Y>)getValueProvider()::apply).andThen(Y::getValue)Y est le type, apply(input) retourne.

Notez que la règle dit "Remplacer les lambdas par des références de méthode si possible" ce qui vous donne la possibilité de dire "bien ici, c'est impossible", cependant, je ne sais pas combien vous pouvez l'appeler une "règle" alors…

31
Holger

si vous codez en Java 8 vous pouvez utiliser la référence de méthode à la place de l'expression lambda pour un code lisible

List<Integer> list = Arrays.asList(1,2,3,4,5);

remplacer ce lambda par une référence de méthode

strList.stream().sorted().collect(Collectors.toList()).forEach(s -> System.out.println(s));

Remplacer

strList.stream().sorted().collect(Collectors.toList()).forEach(System.out::println);
1
Neeraj Gahlawat