1. Java Method References
Method References allow us to define Lambda Expressions by explicitly referring to methods by their names.
Java provides a new feature called Method Reference in Java 8. A method reference is used to refer to a method of a functional interface.
It is a compact and easy form of a Lambda Expression. Whenever a Lambda Expression is used only for referring to an existing method, the Lambda Expression can be replaced with a Method Reference.
Basic Examples
| Method Reference | Equivalent Lambda Expression |
|---|---|
String::toString | s -> s.toString() |
String::toLowerCase | s -> s.toLowerCase() |
String::length | s -> s.length() |
Integer::compareTo | (i1, i2) -> i1.compareTo(i2) |
String::compareTo | (s1, s2) -> s1.compareTo(s2) |
2. Types of Method References
The source describes three main types of Method References:
1. Static Method Reference
Reference to a static method of a class.
ClassName::staticMethodName
2. Instance Method Reference
Reference to an instance/non-static method.
ObjectName::instanceMethodName
3. Constructor Reference
Reference to a class constructor.
ClassName::new
| Case | Lambda Expression | Method Reference Equivalent |
|---|---|---|
| Static Method | (args) -> ClassName.staticMethodName(args) |
ClassName::staticMethodName |
| Instance Method | (args) -> ObjectName.instanceMethodName(args) |
ObjectName::instanceMethodName |
| Constructor | (args) -> new ClassName(args) |
ClassName::new |
3. Lambda Expression vs Method Reference
Example
// Lambda Expression s -> s.toString() // Method Reference String::toString
4. Method Reference to a Static Method of a Class
The PDF uses a functional interface named A and a class named Digit.
interface A {
public boolean checkSingleDigit(int x);
}
class Digit {
public static boolean isSingleDigit(int x) {
return x > -10 && x < 10;
}
}
Using Lambda Expression
public class TestStaticMethodReference {
public static void main(String[] args) {
A a1 = (x) -> {
return x > -10 && x < 10;
};
System.out.println(
a1.checkSingleDigit(10)
);
}
}
Using Method Reference
public class TestStaticMethodReference {
public static void main(String[] args) {
A a2 = Digit::isSingleDigit;
System.out.println(
a2.checkSingleDigit(9)
);
}
}
ClassName::staticMethodName
5. Method Reference to an Instance Method of a Class
interface B {
public void add(int x, int y);
}
class Addition {
public void sum(int a, int b) {
System.out.println(
"The sum is :" + (a + b)
);
}
}
Using Lambda Expression
public class TestInstanceMethodReference {
public static void main(String[] args) {
Addition addition = new Addition();
B b1 = (a, b) ->
System.out.println(
"The sum is :" + (a + b)
);
b1.add(10, 14);
}
}
Using Method Reference
public class TestInstanceMethodReference {
public static void main(String[] args) {
Addition addition = new Addition();
B b2 = addition::sum;
b2.add(100, 140);
}
}
ObjectName::instanceMethodName
6. Constructor Reference
A Constructor Reference provides a compact way to refer to a constructor using ClassName::new.
interface C {
public Employee getEmployee();
}
interface D {
public Employee getEmployee(
String name,
int age
);
}
class Employee {
String eName;
int eAge;
public Employee() {}
public Employee(
String eName,
int eAge) {
this.eName = eName;
this.eAge = eAge;
}
public void getInfo() {
System.out.println(
"I am a method of class Employee"
);
}
}
Using Lambda Expression
C c1 = () -> new Employee();
c1.getEmployee().getInfo();
D d1 = (name, age) ->
new Employee(name, age);
d1.getEmployee("Tony", 34).getInfo();
Using Constructor Reference
C c2 = Employee::new;
c2.getEmployee().getInfo();
D d2 = Employee::new;
d2.getEmployee("Tony", 34).getInfo();
ClassName::new
7. Static Method Reference with List.forEach()
The source demonstrates passing a static method reference to List.forEach().
public class MainStaticReference {
public static void main(String[] args) {
List<String> list =
Arrays.asList("Hello", "World");
list.forEach(
Utils::printMessage
); // static method reference
}
}
Utility Class
package com.fortress.java.preparation;
public class Utils {
public static void printMessage(
String message) {
System.out.println(message);
}
}
8. Instance Method Reference of a Particular Object
The source demonstrates a method reference to a specific object instance.
public class MainInstanceMethodReference {
public static void main(String[] args) {
Printer printer = new Printer();
List<String> list =
Arrays.asList("Java", "8");
list.forEach(
printer::print
); // instance method reference
}
}
printer::print points to the print() method belonging to the particular printer object.
9. Instance Method Reference of an Arbitrary Object of a Particular Type
The PDF also demonstrates a method reference where the method is called on each object supplied by the stream/collection operation.
public class MainArbitraryObject {
public static void main(String[] args) {
List<String> names =
Arrays.asList(
"srikanth",
"vihas",
"kalyani"
);
names.sort(
String::compareToIgnoreCase
); // instance method reference
}
}
Another Example from the Source
List<String> names =
Arrays.asList(
"Alice",
"bob",
"Charlie"
);
names.sort(
String::compareToIgnoreCase
); // sort ignoring case
names.forEach(
System.out::println
); // print using System.out.println
10. Constructor Reference with Supplier
The source demonstrates using a constructor reference with the Supplier functional interface.
import java.util.function.Supplier;
public class MainMethodReferenceConstructor {
public static void main(String[] args) {
Supplier<MyClass> supplier =
MyClass::new; // constructor reference
MyClass obj =
supplier.get(); // invokes constructor
}
}
11. Complete Method Reference Demonstration
Static Method
static class Utils {
public static void printStatic(
String message) {
System.out.println(
"[Static] " + message
);
}
}
Instance Method of a Particular Object
static class Printer {
public void printInstance(
String message) {
System.out.println(
"[Instance] " + message
);
}
}
Constructor
static class MyClass {
public MyClass() {
System.out.println(
"[Constructor] MyClass object created!"
);
}
}
Using All Four Forms
public static void main(String[] args) {
List<String> messages =
Arrays.asList(
"Java",
"Method",
"Reference"
);
// 1. Static Method Reference
messages.forEach(
Utils::printStatic
);
// 2. Instance Method of a Particular Object
Printer printer = new Printer();
messages.forEach(
printer::printInstance
);
// 3. Instance Method of an Arbitrary Object
// of a Particular Type
List<String> names =
Arrays.asList(
"Alice",
"bob",
"Charlie"
);
names.sort(
String::compareToIgnoreCase
); // sort ignoring case
names.forEach(
System.out::println
);
// 4. Constructor Reference
Supplier<MyClass> supplier =
MyClass::new;
MyClass obj =
supplier.get(); // invokes constructor
}
12. Quick Revision
| Type | Syntax | Equivalent Lambda |
|---|---|---|
| Static Method | ClassName::staticMethodName |
(args) -> ClassName.staticMethodName(args) |
| Instance Method — Particular Object | ObjectName::instanceMethodName |
(args) -> ObjectName.instanceMethodName(args) |
| Instance Method — Arbitrary Object | ClassName::instanceMethodName |
Method invoked on the object supplied by the functional operation. |
| Constructor | ClassName::new |
(args) -> new ClassName(args) |
Easy Memory Trick
Static
ClassName::method
No object is required.
Particular Object
object::method
Uses a specific object.
Arbitrary Object
ClassName::method
Method operates on objects supplied by the functional operation.
Constructor
ClassName::new
Creates a new object.