静态上下文无法访问收集器中的非静态

Jud*_*han 26 collect java-8 java-stream method-reference

我有一群学生.首先,我想用标记对它们进行分组.然后我想进一步将这些集合分组到同名学生中.

   Map<Integer,Map<String,List<String>>> groupping = students.stream()
                                                        .collect(Collectors.groupingBy(Student::getMarks, 
                                                                Collectors.mapping(Student::getName,Collectors.toList())));
Run Code Online (Sandbox Code Playgroud)

我收到一个错误说,

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

是.我非常清楚,如果没有实例,我就无法引用非静态方法.但是对于所有这些流操作,我真的很困惑.

而不是如何解决这个问题; 我真的想知道这里发生了什么.您的任何投入都表示赞赏!

因为如果我写下面的分组是完全有效的;

    Map<Integer,List<Student>> m = students.stream().
            collect(Collectors.groupingBy(Student::getMarks));
Run Code Online (Sandbox Code Playgroud)

这是我的Student.java类(如果你需要的话)

public class Student {

    private String name;
    private int marks;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getMarks() {
        return marks;
    }

    public void setMarks(int marks) {
        this.marks = marks;
    }

    public Student(String name, int marks) {

        this.name = name;
        this.marks = marks;
    }

    @Override
    public String toString() {
        return name + ':' + marks ;
    }
}
Run Code Online (Sandbox Code Playgroud)

Hol*_*ger 53

不幸的是,当涉及方法引用时,错误消息" 非静态方法不能从静态上下文中引用."只是任何类型不匹配问题的占位符.编译器根本无法确定实际问题.

在您的代码中,目标类型Map<Integer, Map<String, List<String>>>与组合收集器的结果类型不匹配Map<Integer, List<String>>,但是编译器没有尝试确定此(独立)结果类型,因为(嵌套)泛型方法调用包含方法引用需要目标类型来解析方法引用.因此,它不会报告赋值的类型不匹配,而是解决方法引用的问题.

正确的代码就是

Map<Integer, List<String>> groupping = students.stream()
    .collect(Collectors.groupingBy(Student::getMarks, 
             Collectors.mapping(Student::getName, Collectors.toList())));
Run Code Online (Sandbox Code Playgroud)

  • 组合收集器是 `groupingBy(Student::getMarks, mapping(Student::getName, toList()))`,如果我们将其视为独立表达式(就像所有表达式都在 Java 8 之前一样),它将具有结果类型)。如果规则是这样,编译器会报告一个简单的 `Map&lt;Integer, List&lt;String&gt;&gt;` cannot be assignment to `Map&lt;Integer,Map&lt;String,List&lt;String&gt;&gt;&gt;` 错误消息。 (2认同)
  • 不幸的是,Java 8 规则不再那么简单了。对于所谓的“poly 表达式”,目标类型决定了结果类型,因此您可以将 `groupping` 声明为 `Map&lt;Object,List&lt;CharSequence&gt;&gt;`,不会有任何错误。这将改进方法引用的函数类型,例如`Student::getMarks` 将是`Function&lt;Student,Object&gt;` 而`Student::getName` 将是`Function&lt;Student,CharSequence&gt;`。奇怪的错误消息源于试图为错误的目标类型找到合适的方法。 (2认同)