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 ?
:: is a new operator included in Java 8 that is used to refer to a method of an existing class. You can refer to static methods and non-static methods of a class. The only prerequisite for referring to a method is that the method exists in a functional interface, which must be compatible with the method reference.
The double colon (::) operator, also known as method reference operator in Java, is used to call a method by referring to it with the help of its class directly. They behave exactly as the lambda expressions.
In Java 8, the double colon (::) operator is called method references. Refer to the following examples: Anonymous class to print a list.
Notice that method references always utilize the :: operator.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With