public class Car {
private int maxSpeed;
public Car(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
public int getMaxSpeed() {
return maxSpeed;
}
}
We can sort a list of cars by,
Car carX = new Car(155);
Car carY = new Car(140);
List<Car> cars = new ArrayList<>();
cars.add(carX);
cars.add(carY);
cars.sort(Comparator.comparing(Car::getMaxSpeed));
If we see the signature of the method Comparator.comparing
, the input parameter type is Function<? super T, ? extends U>
In the above example, how is Car::getMaxSpeed
being cast to Function<? super T, ? extends U>
while the following does not compile?
Function<Void, Integer> function = Car::getMaxSpeed;
Java provides a new feature called method reference in Java 8. Method reference is used to refer method of functional interface. It is compact and easy form of lambda expression. Each time when you are using lambda expression to just referring a method, you can replace your lambda expression with method reference.
Method Reference in java 8 makes the code simple and more readable than lambda expression. Method reference refers to the method via the use of an :: operator. A method reference in Java 8 can execute only a single method call like a lambda expression but a shorter code.
A method reference is similar to lambda expression used to refer a method without invoking it while constructor reference used to refer to the constructor without instantiating the named class. A method reference requires a target type similar to lambda expressions.
The assignment:
Function<Void, Integer> function = carX::getMaxSpeed;
does not compile because it's a Supplier<Integer>
, not a Function
.
So then, why does this compile?:
Comparator.comparing(Car::getMaxSpeed)
Java 8 allows an instance method reference that is a Supplier<U>
to be provided where a Function<T, U>
is expected, and the compiler effectively converts the getter method into a function.
To find out why this is possible, let's look at how we invoke a getter method using reflection:
System.out.println(Car.class.getMethod("getMaxSpeed").invoke(carX)); // "155"
When calling invoke()
on an instance method, we pass the instance to the invoke()
method of the getter's Method
- there's an implied parameter of the instance type. When looked at it this way, we see that under the hood a getter is really implemented as a Function<T, U>
via the invoke()
method.
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