Java 8 method reference with example

As a lot has been done in terms of advancement to Java, one of them is method reference.

Before Java 8 we use anonymous classes, but with Java 8 we can use lambda expressions to create anonymous methods. But Sometimes, a lambda expression does nothing, except calling an existing method. In those cases, it’s often clearer to refer to the existing method by their name instead.

Method references enable you to do this, they are compact, easy-to-read lambda expressions for methods that already have a name.

As stated above sometimes a lambda expression only invokes a method, refer to the below code snippet.

List<String> name = Arrays.asList("Tom","and","Jerry");

Consumer<String> c = s -> System.out.println(s);

name.forEach(c);

By turning the above lambda expression into a method reference we can make the code more cleaner as below.

List<String> name = Arrays.asList("Tom","and","Jerry");

Consumer<String> c = System.out::println;

name.forEach(c);

So instead of using AN ANONYMOUS CLASS, we can use A LAMBDA EXPRESSION and if this just calls one method, we can use A METHOD REFERENCE.

Types of Method Reference:

Method Reference TypeExample
Reference to a static methodContainingClass::staticMethodName
Reference to an instance method of a particular objectcontainingObject::instanceMethodName
Reference to an instance method of an arbitrary object of a particular typeContainingType::methodName
Reference to a constructorClassName::new

Let’s understand these in more detail one by one.

Static method reference:

Invoking a static method of class by ClassName::someStaticMethodName instead of ClassName.someStaticMethodName(). Note the :: and no brackets in method reference.

Let’s try an example of method reference:

class Device{
	int id;
	String type;

	public Device(int id, String type) {
		super();
		this.id = id;
		this.type = type;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	@Override
	public String toString() {
		return "Device [id=" + id + ", type=" + type + "]";
	}
}
public class ExampleOfMethodReference {

    public static void main(String[] args) {

       List<Device> devices = Arrays.asList(
	new Device(1, "Mobile"),
	new Device(3,"Laptop"),
	new Device(2, "PC"),
	new Device(5, "Router"),
	new Device(4, "Mouse"));   

     System.out.println("devices before sort");
     System.out.println(devices);

     Comparator<Device> compt = ExampleOfMethodReference::compareById;

     Collections.sort(devices,compt);

     System.out.println("devices after sort");

     System.out.println(devices);

  }

   public static int compareById(Device d1, Device d2) {
     return Integer.compare(d1.getId(), d2.getId());
  }
}

Output:

devices before sort
[Device [id=1, type=Mobile], Device [id=3, type=Laptop], Device [id=2, type=PC], Device [id=5, type=Router], Device [id=4, type=Mouse]]
devices after sort
[Device [id=1, type=Mobile], Device [id=2, type=PC], Device [id=3, type=Laptop], Device [id=4, type=Mouse], Device [id=5, type=Router]]

Instance Method Reference of a Particular Object

When you invoke the instance method of the particular object, you will use the containingObjectReference::someInstanceMethodName

Refer below code snippet and the output:

public class ExampleOfMethodReference {

	public static void main(String[] args) {

	List<Device> devices = Arrays.asList(
		new Device(1, "Mobile"),
		new Device(3,"Laptop"),
		new Device(2, "PC"),
		new Device(5, "Router"),
		new Device(4, "Mouse"));   

	System.out.println("devices before sort using instace method");
	System.out.println(devices);

	ExampleOfMethodReference ec = new ExampleOfMethodReference();

	Collections.sort(devices,ec::compareById);

	System.out.println("devices after sort using instace method");

	System.out.println(devices);

	}
	public int compareById(Device d1, Device d2) {
		return Integer.compare(d1.getId(), d2.getId());
	}
}

Output:

devices before sort
[Device [id=1, type=Mobile], Device [id=3, type=Laptop], Device [id=2, type=PC], Device [id=5, type=Router], Device [id=4, type=Mouse]]
devices after sort using instace method
[Device [id=1, type=Mobile], Device [id=2, type=PC], Device [id=3, type=Laptop], Device [id=4, type=Mouse], Device [id=5, type=Router]]

Instance Method Reference of an Arbitrary Object

By accessing an instance method of a class with the ClassName, you will get the instance method reference of an arbitrary object of a particular type, such asClassName::someInstanceMethod;

Refer below code snippet and the output:

public class ExampleOfMethodReference {

	public static void main(String[] args) {

	List<Device> devices = Arrays.asList(
		new Device(1, "Mobile"),
		new Device(3,"Laptop"),
		new Device(2, "PC"),
		new Device(5, "Router"),
		new Device(4, "Mouse"));   

	Map<Integer, String> deviceMap = devices.stream().collect(Collectors.toMap(Device::getId, Device::getType));

	System.out.println("deviceMap "+deviceMap);
	}
}

Output:

deviceMap {1=Mobile, 2=PC, 3=Laptop, 4=Mouse, 5=Router}

Constructor Reference

By calling the constructor of a class by class name in lambda, you will get a constructor reference, such as ClassName::new.

Refer below code snippet and the output:

public class ExampleOfMethodReference {

	public static void main(String[] args) {

	List<Integer> integers = IntStream.range(1, 10).boxed()
         .collect(Collectors.toCollection( ArrayList::new ));

	System.out.println(integers);

	}
}

Output:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

That’s it on Java method reference. Read more on Java 8 features.
Java 8 Default and Static method in Interface
Java 8 functional interface
Java 8 Predicates
Java 8 Default and Static method in Interface
Java 8 forEach method in Iterable Interface

Reference

Oracle doc

Happy Learning !!

Leave a Comment