Java Method reference not expected here

爷,独闯天下 提交于 2021-02-07 14:26:28

问题


How exactly do you chain method references for instances with Java 8? Example:

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

getStrategy of a Civilization instance returns a Strategy object instance which has the instance method getStrategyLevel.

Why doesn't the Comparator.comparing method return a comparator with it's functional interface implemented by the lambda expression?


回答1:


In that case, you should use a lambda, you can't apply a method reference directly:

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

Though, there is a way to use a method reference here. Assuming that you have a class like

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

the issue could be solved like

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



回答2:


You cannot do it with a method reference, you need to use a lambda expression or create a static method.

There are four kinds of method references:

  1. Reference to a static method like ContainingClass::staticMethodName
  2. Reference to an instance method of a particular object like containingObject::instanceMethodName
  3. Reference to an instance method of an arbitrary object of a particular type like ContainingType::methodName
  4. Reference to a constructor like ClassName::new

More details about method reference.

So here, with a lambda expression it would be:

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

Or in case you create a static method

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

Then your code would be:

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



回答3:


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



回答4:


Different example, but I have a method

void m(Predicate<String> stringPredicate)

and a utility class

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

and I wanted to invoke m with a predicate that returns true iff Utilities.condition1 returns false. The Java grammar allows me to write

m(Utilities::condition1)

but not

m(Utilities::condition1.negate())

(an unfortunate violation of referential transparency), and the compiler complained, "Java Method reference not expected here."

My workaround was to write a method

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

and then to write the call

m(not(Utilities::condition1))

--which is allowed by the Java grammar.



来源:https://stackoverflow.com/questions/40440548/java-method-reference-not-expected-here

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!