问题
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:
- Reference to a static method like
ContainingClass::staticMethodName
- Reference to an instance method of a particular object like
containingObject::instanceMethodName
- Reference to an instance method of an arbitrary object of a particular type like
ContainingType::methodName
- 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