I was exploring the Java 8 source and found this particular part of code very surprising:
//defined in IntPipeline.java @Override public final OptionalInt reduce(IntBinaryOperator op) { return evaluate(ReduceOps.makeInt(op)); } @Override public final OptionalInt max() { return reduce(Math::max); //this is the gotcha line } //defined in Math.java public static int max(int a, int b) { return (a >= b) ? a : b; }
Is Math::max
something like a method pointer? How does a normal static
method gets converted to IntBinaryOperator
?
:: is called Method Reference. It is basically a reference to a single method. i.e. it refers to an existing method by name. Method reference using :: is a convenience operator. Method reference is one of the features belonging to Java lambda expressions.
The double colon ( :: ) may refer to: an analogy symbolism operator, in logic and mathematics. a notation for equality of ratios. a scope resolution operator, in computer programming languages.
Don't think colon(:) means anything particularly. It's just how Java designers thought to delimit parameter and expression inside improved for loop.
It is simple to label a loop, place the label before the loop with a colon at the end as shown below in the example: public class ColonJava3 { public static void main(String args[]) { int i, j=0; //outer label outerloop: for(i=0; i < 3; i++) { System.
Usually, one would call the reduce
method using Math.max(int, int)
as follows:
reduce(new IntBinaryOperator() { int applyAsInt(int left, int right) { return Math.max(left, right); } });
That requires a lot of syntax for just calling Math.max
. That's where lambda expressions come into play. Since Java 8 it is allowed to do the same thing in a much shorter way:
reduce((int left, int right) -> Math.max(left, right));
How does this work? The java compiler "detects", that you want to implement a method that accepts two int
s and returns one int
. This is equivalent to the formal parameters of the one and only method of interface IntBinaryOperator
(the parameter of method reduce
you want to call). So the compiler does the rest for you - it just assumes you want to implement IntBinaryOperator
.
But as Math.max(int, int)
itself fulfills the formal requirements of IntBinaryOperator
, it can be used directly. Because Java 7 does not have any syntax that allows a method itself to be passed as an argument (you can only pass method results, but never method references), the ::
syntax was introduced in Java 8 to reference methods:
reduce(Math::max);
Note that this will be interpreted by the compiler, not by the JVM at runtime! Although it produces different bytecodes for all three code snippets, they are semantically equal, so the last two can be considered to be short (and probably more efficient) versions of the IntBinaryOperator
implementation above!
(See also Translation of Lambda Expressions)
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