问题
In Java 8 method references are done using the ::
operator.
For Example
// Class that provides the functionality via it's static method
public class AddableUtil {
public static int addThemUp(int i1, int i2){
return i1+i2;
}
}
// Test class
public class AddableTest {
// Lambda expression using static method on a separate class
IAddable addableViaMethodReference = AddableUtil::addThemUp;
...
}
You can see that the addableViaMethodReference
now acts like an alias to AddableUtil::addThemUp
. So addableViaMethodReference()
will perform the same action as AddableUtil.addThemUp()
and return the same value.
Why did they choose to introduce a new operator instead of using an existing one ? I mean, execute a function when the function name ends with ()
and return the function reference when there is no trailing ()
.
Method Execution
AddableUtil.addThemUp();
Method reference
AddableUtil.addThemUp;
Wouldn't this be much simpler and intuitive ? AFAIK, AddableUtil.addThemUp
doesn't currently (Java 7) serve any other purpose and throws a compilation error. Why not use that opportunity instead of creating an entirely new operator ?
回答1:
The following piece of code compiles fine in Java 8, but would be ambiguous without a new operator:
import java.util.function.IntBinaryOperator;
public class A {
public static IntBinaryOperator addThemUp;
public static int addThemUp(int i1, int i2) {
return i1 + i2;
}
public static void main(String[] args) throws Exception {
IntBinaryOperator operator = A::addThemUp;
}
}
It wouldn't be clear whether A.addThemUp
refers to the public IntBinaryOperator
field or is an attempt to create a method reference.
Yes, it's a bit contrived. But you can't allow edge cases in programming language syntax.
回答2:
Fields and methods have separate name spaces, so there is the possibility of an ambiguity between a method name and a field name (which might then require even more rules to disambiguate). This is definitely a big problem for the "reuse some existing syntax" approach (which was, BTW, considered as a candidate, as were a number of other possibilities.)
But, I would turn the question around: is "overloading" an existing syntax like this really a good idea? (Your question assumes this, but this is an enormous assumption.) There's a big difference between "call method m / read field f" and "refer to method m / field f by name". Shouldn't the two kinds of expressions look different? What is the benefit of reusing an existing syntax to mean something completely different?
Further, there's a scalability issue with the approach you suggest: we'd never be able to do field references in the future without inventing a new syntax, which would then be different from the syntax for method references. While field references were not a must-have for lambda, never being able to finish the job here would be a big minus.
These are just a few of the various considerations that fed into this decision. In hindsight, I still think we made the right call here.
回答3:
Maybe they did it to make the C++ programmers feel more welcome in Java? /* In my opinion (dangerous words to use as a skeptic), operator:: is more natural to use on static methods, as it is the scope resolution operator in C++ */
来源:https://stackoverflow.com/questions/26590453/why-did-java-8-introduce-a-new-operator-for-method-references