方法引用自定义类方法

时间:2017-04-13 14:48:45

标签: java java-8

我有以下代码:

    Map<String, ReportConfig> reportConfigMap = reportFactory.getReportConfigMap();

    List<String> resultList = reportConfigMap.values()
            .parallelStream()
            .filter(Utility::shouldReportVisibleToUser)
            .map(ReportConfig::getName)
            .collect(Collectors.toList());

ReportConfig类代码

public class ReportConfig implements Comparable<ReportConfig> {
  private String name;
  public String getName() {
        return name;
    }

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

对于代码.map(ReportConfig::getName)的部分,我使用ReportConfig::getName传递getName方法的方法引用,看起来好像getName是ReportConfig类的静态方法,但实际上它是非静态方法那个班。

如果我尝试在自定义函数中执行相同的操作,那么java会给出错误,其中包含:Cannot make a static reference to the non-static method。例如,以下代码将无效:

    public class Test{
      public static void main (String[] agrs){
         Test test = new Test();
         test.executeService(Test::test);
      }
      public static ReportConfig executeService(Function<? extends ReportConfig,? extends ReportConfig> mapper){
        return mapper.apply(null);
      }

      public ReportConfig test(ReportConfig r){
        return r;
      }

    }

我的问题是如果为map方法工作而不是为我的自定义方法工作?有什么我做错了或者我完全误解了什么吗?

1 个答案:

答案 0 :(得分:3)

ReportConfig::getName is roughly equivalent to:

public static String getName(ReportConfig arbitraryObject) {
    ...
}

The compiler searches the ReportConfig class for a method that matches the above signature. Since instance methods implicitly take this as the first parameter, the compiler finds the instance method getName() to be applicable. Furthermore, this signature matches the type arguments of a Function<ReportConfig, String>, so everything works fine.

On the other hand, going with the same inference as above, Test::test would be equivalent to:

public static ReportConfig test(Test arbitraryObject, ReportConfig r) {
    return r;
}

In this case, the compiler finds the method public ReportConfig test(ReportConfig r) which matches the above signature, but which cannot be converted to a Function<? extends ReportConfig,? extends ReportConfig> (it would be converted to a BiFunction<Test, ReportConfig, ReportConfig> instead). Therefore the compiler resorts to finding a static test method, which does not exist.

To make it compile, either make the test method static, or use test::test instead of Test::test.