JAVA_STREAM-API_E-5
๐น Method Reference (::)
โค Introduction
- It is a new feature introduced in JDK 1.8.
- It is an improvement over a lambda expression.
- While working with lambda, we need to provide the method body (implementation).
- By using Method Reference (::), we can refer existing method at the project level or the Java API level.
- To refer to an existing method, we use a double colon (::).
- We can refer to any type of method:
- Static method
- Non-static method
- Constructor
๐น Types of Method Reference
It is divided into 4 types:
- Instance Method Reference
objectName::instanceMethodName - Static Method Reference
ClassName::staticMethodName - Constructor Reference
ClassName::new - Arbitrary Object Method Reference
ClassName::instanceMethodName
๐น 1) Program on Instance Method Reference
package com.ravi.method_ref;
@FunctionalInterface
interface Worker {
void work();
}
public class MethodReference {
public static void main(String[] args) {
// Lambda
Worker w = () -> System.out.println("Worker is working...");
w.work();
// Method Reference
Worker w1 = new Employee()::work;
w1.work();
}
}
class Employee {
public void work() {
System.out.println("Employee is working");
}
}๐น 2) Static Method Reference
(ClassName::staticMethodName)
Get Aman Vermaโs stories inย yourย inbox
Join Medium for free to get updates fromย thisย writer.
โก The following program explains that the interface abstract method name and the method reference method name may be the same or different, butthe parameter list and return type must be the same.
package com.ravi.method_ref;
@FunctionalInterface
interface Worker {
void work();
}
public class MethodReference {
public static void main(String[] args) {
Worker w = Employee::salary;
w.work();
}
}
class Employee {
public static void salary() {
System.out.println("Employee is working for Salary");
}
}๐น 3) Constructor Reference (ClassName::new)
package com.ravi.constructor_ref;
import java.util.function.Supplier;
class Sample {
public Sample() {
System.out.println("No Argument constructor of Sample class");
}
public void greet() {
System.out.println("Hello Everyone");
}
}
public class Demo1 {
public static void main(String[] args) {
Supplier<Sample> s1 = Sample::new;
Sample sample = s1.get();
sample.greet();
}
}๐น Constructor Reference with Parameterized Constructor
package com.ravi.constructor_ref;
import java.util.function.Function;
class Student {
private String name;
public Student(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [name=" + name + "]";
}
}
public class Demo2 {
public static void main(String[] args) {
Function<String, Student> fn1 = Student::new;
Student student = fn1.apply("Ravi");
System.out.println(student);
}
}๐น Parameterized Constructor (Multiple Parameters)
package com.ravi.constructor_ref;
import java.util.function.BiFunction;
class Employee {
private Integer id;
private String name;
public Employee(Integer id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + "]";
}
}
public class Demo3 {
public static void main(String[] args) {
BiFunction<Integer, String, Employee> fn1 = Employee::new;
Employee obj = fn1.apply(12, "James");
System.out.println(obj);
}
}๐น Creating an Array using a Constructor Reference
package com.ravi.constructor_ref;
import java.util.function.Function;
record Customer(Integer id, String name) {}
public class Demo4 {
public static void main(String[] args) {
Function<Integer, Customer[]> fn = Customer[]::new;
int size = 3;
Customer[] customers = fn.apply(size);
customers[0] = new Customer(1, "Ravi");
customers[1] = new Customer(2, "Rahul");
customers[2] = new Customer(3, "Raj");
System.out.println("Printing the Customer Data:");
for (Customer customer : customers) {
System.out.println(customer);
}
}
}๐น 4) Arbitrary Method Reference
(ClassName::instanceMethodName)
โ Arbitrary means any type of object.
โ By using this technique, we can directly call a non-static method with the class name.
โ Internally, the JVM passes the object automatically.
Example:
Lambda Expression Method References
- s -> s.length() String::length
- (i1, i2) -> i1.compareTo( i2) Integer::compareTo
- s -> s.toUpperCase() String::toUpperCase
๐น Program Example 1
package com.ravi.arbit_ref_type;
import java.util.function.Function;
public class ArbitraryRefDemo1 {
public static void main(String[] args) {
Function<String, String> fn1 = String::toUpperCase;
System.out.println(fn1.apply("java"));
System.out.println(fn1.apply("stream"));
}
}๐น Program Example 2
package com.ravi.arbit_ref_type;
import java.util.TreeSet;
public class ArbitraryRefDemo2 {
public static void main(String[] args) {
TreeSet<String> ts = new TreeSet<>(String::compareTo);
ts.add("C");
ts.add("D");
ts.add("A");
System.out.println(ts);
TreeSet<String> ts1 =
new TreeSet<>((s1, s2) -> s2.compareTo(s1));
ts1.add("C");
ts1.add("D");
ts1.add("A");
System.out.println(ts1);
}
}๐น Limitation of Method Reference
- We need to executethe already existing method.
- We cannot modify the method body.
- If customization is required, we should use a Lambda Expression.
๐น Sorting Example (Lambda vs Method Reference)
package com.ravi.arbit_ref_type;
import java.util.*;
public class ArbitraryRefDemo3 {
public static void main(String[] args) {
List<Integer> listOfNumbers =
Arrays.asList(9, 5, 6, 2, 4, 1);
// By using Lambda
Collections.sort(listOfNumbers,
(i1, i2) -> i2.compareTo(i1));
listOfNumbers.forEach(System.out::println);
System.out.println("------------------");
// By using Method Reference
Collections.sort(listOfNumbers,
Integer::compareTo);
listOfNumbers.forEach(System.out::println);
// Sorting Strings
String[] players =
{"Virat", "Rohit", "Zaheer", "Rishab", "Abhishek"};
Arrays.sort(players,
String::compareTo);
System.out.println(Arrays.toString(players));
}
}๐น Internal Working of Arbitrary Method Reference
package com.ravi.arbit_ref_type;
@FunctionalInterface
interface MyFunction<T, U, V, R> {
R myApply(T t, U u, V v);
}
public class ArbitraryReferenceDemo4 {
public static void main(String[] args) {
// Lambda
MyFunction<Addition, String, String, Integer> myLambda =
(add, str1, str2) -> add.doSum(str1, str2);
System.out.println(
myLambda.myApply(new Addition(), "100", "200"));
// Method Reference
MyFunction<Addition, String, String, Integer> myRef =
Addition::doSum;
System.out.println(
myRef.myApply(new Addition(), "500", "400"));
}
}
class Addition {
public Integer doSum(String n1, String n2) {
return Integer.parseInt(n1)
+ Integer.parseInt(n2);
}
}โ Final Conclusion
โ Method Reference is cleaner and shorter than Lambda.
โ Used when implementation already exists.
โ Introduced in Java 8.
โ Works only with Functional Interfaces.







