【问题标题】:Java Method reference not expected here此处不应有 Java 方法参考
【发布时间】:2016-11-05 16:27:09
【问题描述】:

对于 Java 8 实例,您究竟是如何链接方法引用的?示例:

Collections.sort(civs,Comparator.comparing(Civilization::getStrategy.getStrategLevel));

Civilization 实例的getStrategy 返回具有实例方法getStrategyLevelStrategy 对象实例。

为什么Comparator.comparing 方法不返回一个比较器,它的功能接口由 lambda 表达式实现?

【问题讨论】:

  • 只需使用 lambda。
  • 方法引用是对方法的引用。链“调用getStrategy(),然后在结果上调用getStrategyLevel())不是方法,因此不适合用方法引用来描述。如果要描述任意包的命令式代码,请使用lambda;方法引用是为特殊情况提供的(希望更具可读性)简写,其中 lambda 主体是单个方法,其参数列表与目标函数接口的参数列表完全匹配。

标签: java lambda java-8 comparator method-reference


【解决方案1】:

在这种情况下,你应该使用 lambda,你不能直接应用方法引用:

Collections.sort(civs, Collectors.comparing(c -> c.getStrategy().getStrategLevel()));

不过,这里有一种使用方法引用的方法。假设你有一个类似的类

class CivilizationUtils {
    public static Integer getKeyExtractor(Civilization c) {
        return c.getStrategy().getStrategLevel();
    }
}

问题可以这样解决

Collections.sort(civs, Collectors.comparing(CivilizationUtils::getKeyExtractor));

【讨论】:

  • getStrategy 不是静态方法
  • 如何通过Strategy 的实例提供对实例方法getStrategyLevel 的方法引用,该实例通过Civilization 的实例访问。我应该只为比较器使用常规 lambda 表达式吗?
【解决方案2】:

你不能用方法引用来做到这一点,你需要使用 lambda 表达式或创建一个静态方法。

方法引用有四种:

  1. 引用一个静态方法,比如ContainingClass::staticMethodName
  2. 特定对象的实例方法的引用,例如containingObject::instanceMethodName
  3. 引用特定类型的任意对象的实例方法,例如ContainingType::methodName
  4. 构造函数的引用,例如ClassName::new

更多关于method reference的细节。

所以在这里,lambda expression 将是:

Collections.sort(civs, Comparator.comparing(c -> c.getStrategy.getStrategLevel()));

或者如果你创建一个静态方法

public static int getStrategLevel(Civilization c) {
    return c.getStrategy().getStrategLevel();
}

那么您的代码将是:

Collections.sort(civs, Comparator.comparing(MyClass::getStrategLevel));

【讨论】:

    【解决方案3】:
    Collections.sort(civs,Comparator.comparing(civ -> civ.getStrategy().getStrategLevel()));
    

    【讨论】:

      【解决方案4】:

      不同的例子,但我有一个方法

      void m(Predicate<String> stringPredicate)
      

      还有一个实用类

      class Utilities {
        static boolean condition1(String s) { ... }
        static boolean condition2(String s) { ... }
        ...
      }
      

      我想用一个返回 true 的谓词调用 m,如果 Utilities.condition1 返回 false。 Java语法允许我写

      m(Utilities::condition1)
      

      但不是

      m(Utilities::condition1.negate())
      

      (不幸地违反了referential transparency),编译器抱怨说,“这里不应该有Java方法引用。”

      我的解决方法是写一个方法

      Predicate<String> not(Predicate<String> p) {
        return p;
      }
      

      然后写调用

      m(not(Utilities::condition1))
      

      --这是Java语法允许的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多