无法从java 8流中的静态上下文引用非静态方法 [英] Non-static method cannot be referenced from a static context in java 8 streams

查看:7759
本文介绍了无法从java 8流中的静态上下文引用非静态方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在玩 http:/ /www.concretepage.com/java/jdk-8/java-8-unaryoperator-binaryoperator-example

我觉得很困惑的是,我在编写收集器时错误地将错误类型放入泛型中,java编译器给了我一个非常误导性的消息:

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:


非静态方法不能从静态上下文引用

Non-static method cannot be referenced from a static context

我的错误与静态vs实例上下文无关:

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

一切恢复正常。

有人可以解释这种令人困惑的错误消息背后的原因吗?我确定这是一个很好的,但我没有掌握它。

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.

编辑:

~$ 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)


推荐答案

首先应该注意,消息不是由java编译器(javac)发出的,而是由IntelliJ IDEA发出的。实际启动构建过程时,可以在Messages Build窗口中看到javac消息。您在编辑器窗口中看到的是IDEA本身生成的消息,它们可能不同。

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.

由于在IntelliJ IDEA中实现了方法参考分辨率,错误消息具有误导性。只有当相应的SAM(单个抽象方法)参数的数量等于方法参数的数量加上一个时,它才会解析非静态方法引用,第一个SAM参数类型与包含类的方法兼容。参见实现(上面还有 isSecondSearchPossible 方法,为varargs方法执行了一些额外的魔术)。

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 and the 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).

如果程序没有错误,它可以正常工作。但是,如果您的类型不匹配,则无法替换传递到 toMap Function 的泛型参数,因此它仍然存在功能< T,R> ,其 apply 方法第一个参数只是 T 学生类型不对应。因此,所谓的第二次搜索失败,IDEA认为该方法是从静态上下文引用的。虽然静态和非静态上下文在这里都不适用,但非静态上下文更符合您的方法,至少根据参数的数量为 getName()方法接收否参数。另一方面,IDEA逻辑是如果非静态上下文不适用,则它是静态上下文,因此是错误消息。

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.

我会认为这是一个bug,或者至少是一个可用性问题。我刚刚根据这里登录了它.com / q / 42237290/4856258>类似问题。希望我们能解决它。

I would consider this as a bug, or at least as a usability problem. I've just logged it here based on similar question. Hopefully we will fix it.

免责声明:我是IntelliJ IDEA开发人员。

Disclaimer: I'm IntelliJ IDEA developer.

更新:已在IDEA 2017.2中修复。

Update: fixed in IDEA 2017.2.

这篇关于无法从java 8流中的静态上下文引用非静态方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆