不能从 java 8 流中的静态上下文引用非静态方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42200958/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Non-static method cannot be referenced from a static context in java 8 streams
提问by yuranos
I was playing around with examples from http://www.concretepage.com/java/jdk-8/java-8-unaryoperator-binaryoperator-example.
我在玩http://www.concretepage.com/java/jdk-8/java-8-unaryoperator-binaryoperator-example 中的例子。
What I find really confusing is that when I mistakenly put a wrong type into one of generics when forming Collectors, java compiler gives me a very misleading message:
我发现真正令人困惑的是,当我在形成收集器时错误地将错误的类型放入泛型之一时,java 编译器给了我一个非常误导的消息:
Non-static method cannot be referenced from a static context
不能从静态上下文中引用非静态方法
My error has nothing to do with static vs instance context in reality:
我的错误实际上与静态与实例上下文无关:
Map<String, Map<Integer, Integer>> mapOfStudents = list.stream().collect(Collectors.groupingBy(Student::getClassName,
Collectors.toMap(Student::getName, Student::getAge)));
My mistake is in generic return type. When I correct it and put:
我的错误在于通用返回类型。当我纠正它并放置时:
Map<String, Map<String, Integer>> mapOfStudents
everything goes back to normal.
一切恢复正常。
Can someone explain the reason behind such a confusing error message? I'm sure the is a good one, but I fail to grasp it.
有人可以解释这种令人困惑的错误消息背后的原因吗?我敢肯定这是一个很好的,但我没有掌握它。
EDIT:
编辑:
~$ 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)
采纳答案by Tagir Valeev
First it should be noted, that the message is issued not by java compiler (javac), but by IntelliJ IDEA. You can see javac messages in "Messages Build" window when you actually launch a build process. What you see in editor window is messages generated by IDEA itself and they could differ.
首先应该注意的是,该消息不是由 java 编译器 (javac) 发出的,而是由 IntelliJ IDEA 发出的。当您实际启动构建过程时,您可以在“消息构建”窗口中看到 javac 消息。您在编辑器窗口中看到的是 IDEA 本身生成的消息,它们可能有所不同。
The error message is misleading due to implementation of method reference resolution in IntelliJ IDEA. It considers non-static method reference to be resolved only if number of corresponding SAM (single abstract method) arguments equals to number of method arguments plus one andthe first SAM argument type is compatible with method containing class. See the implementation(also isSecondSearchPossible
method above, some additional magic is performed for varargs methods).
由于 IntelliJ IDEA 中方法引用解析的实现,错误消息具有误导性。只有当相应的 SAM(单个抽象方法)参数的数量等于方法参数的数量加一个并且第一个 SAM 参数类型与包含类的方法兼容时,它才会考虑解析非静态方法引用。参见实现(也是isSecondSearchPossible
上面的方法,对可变参数方法执行了一些额外的魔法)。
It works correctly if your program has no errors. However if you have a mismatched type, the generic arguments of the Function
passed into toMap
cannot be substituted, so it remains Function<T, R>
, and its apply
method first argument is simply T
which does not correspond to the type Student
. Thus so-called "second search" fails and IDEA thinks that the method is referenced from static context. While both static and non-static context are not applicable here, non-static context matches your method better, at least according to the number of arguments as getName()
method receives no arguments. On the other hand, IDEA logic is "if non-static context is not applicable, then it's a static context", hence the error message.
如果您的程序没有错误,它就可以正常工作。但是,如果您的类型不匹配,则无法替换Function
传入的泛型参数toMap
,因此它仍然是Function<T, R>
,并且其apply
方法的第一个参数只是T
与类型不对应的Student
。因此,所谓的“第二次搜索”失败,IDEA 认为该方法是从静态上下文引用的。虽然静态和非静态上下文在这里都不适用,但非静态上下文更好地匹配您的方法,至少根据getName()
方法不接收参数时的参数数量。另一方面,IDEA 逻辑是“如果非静态上下文不适用,则它是静态上下文”,因此出现错误消息。
I would consider this as a bug, or at least as a usability problem. I've just logged it herebased on similar question. Hopefully we will fix it.
我会认为这是一个错误,或者至少是一个可用性问题。我刚刚根据类似的问题在这里记录了它。希望我们会修复它。
Disclaimer: I'm IntelliJ IDEA developer.
免责声明:我是 IntelliJ IDEA 开发人员。
Update: fixed in IDEA 2017.2.
更新:在 IDEA 2017.2 中修复。