web-dev-qa-db-fra.com

La méthode non statique ne peut pas être référencée à partir d'un contexte statique dans Java 8 flux

Je jouais avec des exemples de http://www.concretepage.com/Java/jdk-8/Java-8-unaryoperator-binaryoperator-example .

Ce que je trouve vraiment déroutant, c'est que lorsque je mets par erreur un mauvais type dans l'un des génériques lors de la formation des collecteurs, Java me donne un message très trompeur:

La méthode non statique ne peut pas être référencée à partir d'un contexte statique

Mon erreur n'a rien à voir avec le contexte statique vs le contexte d'instance en réalité:

Map<String, Map<Integer, Integer>> mapOfStudents = list.stream().collect(Collectors.groupingBy(Student::getClassName,
            Collectors.toMap(Student::getName, Student::getAge)));

Mon erreur est dans le type de retour générique. Quand je le corrige et mets:

Map<String, Map<String, Integer>> mapOfStudents

tout revient à la normale.

Quelqu'un peut-il expliquer la raison d'un tel message d'erreur déroutant? Je suis sûr que c'est un bon, mais je n'arrive pas à le saisir.

MODIFIER:

~$ Java -version
openjdk version "1.8.0_121"
OpenJDK Runtime Environment (build 1.8.0_121-8u121-b13-0ubuntu1.16.04.2-b13)
OpenJDK 64-Bit Server VM (build 25.121-b13, mixed mode)
28
yuranos87

Tout d'abord, il convient de noter que le message est émis non pas par Java (javac), mais par IntelliJ IDEA. Vous pouvez voir les messages javac dans la fenêtre "Messages Build" lorsque vous lancez réellement une génération Ce que vous voyez dans la fenêtre de l'éditeur, ce sont des messages générés par IDEA lui-même et ils peuvent différer.

Le message d'erreur est trompeur en raison de l'implémentation de la résolution de référence de méthode dans IntelliJ IDEA. Il considère que la référence de méthode non statique n'est résolue que si le nombre d'arguments SAM (méthode abstraite unique) correspondants est égal au nombre d'arguments de méthode plus un et le premier type d'argument SAM est compatible avec la méthode contenant classe. Voir l'implémentation (également la méthode isSecondSearchPossible ci-dessus, une magie supplémentaire est effectuée pour les méthodes varargs).

Cela fonctionne correctement si votre programme ne contient aucune erreur. Cependant, si vous avez un type incompatible, les arguments génériques de Function passés dans toMap ne peuvent pas être substitués, il reste donc Function<T, R>, Et sa méthode apply le premier argument est simplement T qui ne correspond pas au type Student. Ainsi, la soi-disant "deuxième recherche" échoue et IDEA pense que la méthode est référencée à partir d'un contexte statique. Bien que le contexte statique et non statique ne soient pas applicables ici, le contexte non statique correspond à votre méthode mieux, au moins en fonction du nombre d'arguments car la méthode getName() ne reçoit aucun argument. Par contre, la logique IDEA est "si le contexte non statique n'est pas applicable, alors c'est un contexte statique ", d'où le message d'erreur.

Je considérerais cela comme un bug, ou du moins comme un problème de convivialité. Je viens de le connecter ici basé sur question similaire . J'espère que nous allons le réparer.

Avertissement: je suis IntelliJ IDEA développeur.

Mise à jour : corrigé dans IDEA 2017.2.

35
Tagir Valeev