Java 8 – Method References

Method References make it clear when referring to the existing method by name.

In the article Lambda Expressions and Functional Interfaces, we use lambda expressions to create anonymous methods and sometimes, calling an existing method is the only thing it does.

When using lambda expression without input arguments or those input arguments doesn’t make sense, we can use Method References to simplify the syntax.

This tutorial introduces four kinds of Method References and how to use them efficiently with some Functional Interfaces.

I. Method References

Method reference points to the method by its name by replacing a single-method lambda expression.
The syntax of a Method reference is: Object/Class/Type :: methodName

For example, the lambda expression:

s -> System.out.print(s)

can be replaced with the method reference:

System.out::print

But we should know that it can’t be used for any method. To use a method reference, we need a lambda expression as a method argument which can be used when having a functional interface (an interface with just one abstract method).

II. Kinds of Method References

There are four kinds of method references:
– Reference to a static method: ContainingClass::staticMethodName
– Reference to an instance method of a particular object: containingObject::instanceMethodName
– Reference to an instance method of an arbitrary object of a particular type: ContainingType::instanceMethodName
– Reference to a constructor: ClassName::new

1. Reference to a static method

We have a static method addition in MathOperation class:

public class MathOperation {
	public static int addition(int a, int b) {
		return (a + b);
	}
}

To use lambda expression, in this case, we should have a function with functional interface ToIntBiFunction as input argument:

	int doOperation(int a, int b, ToIntBiFunction f) {
		return f.applyAsInt(a, b);
	}

And the lambda expression will be used:

int a = 1, b = 2;
doOperation(a, b, (x, y) -> MathOperation.addition(x, y));

Instead, Method Reference makes it lean:

int a = 1, b = 2;
doOperation(a, b, MathOperation::addition);

You can see that we don’t need to add argument (x,y) or Arrow Token (->) to the statement, syntax only requires ContainingClass and staticMethodName with double colon symbol (::) between.
ContainingClass::staticMethodName

2. Reference to an instance method of a particular object

In this kind, we will replace a lambda expression:
(arguments) -> containingObject.instanceMethodName(arguments)
with method reference:
containingObject::instanceMethodName
We have a method getOperationName in MathOperation class:

public class MathOperation {
	public String getOperationName(String operation) {
		if (operation.contains("+")) {
			return "addition";
		} else if (operation.contains("-")) {
			return "subtraction";
		} else {
			return "not detected";
		}
	}
}

A function with functional interface Function as input argument:

	String runOperationName(String operation, Function f) {
		return f.apply(operation);
	}

The lambda expression and Method Reference will be used:

String op = "+";
MathOperation mathOperation = new MathOperation();
// lambda expression
runOperationName(op, s -> mathOperation.getOperationName(s));
// Method Reference
runOperationName(op, mathOperation::getOperationName);
3. Reference to an instance method of an arbitrary object of a particular type

we will replace a lambda expression:
(object) -> object.instanceMethodName()
with method reference:
ContainingTypeofObject::instanceMethodName
We have a method getOperationNameNew in MathOperation class.
The purpose is using the instance object of MathOperation with its property [String operation]:

public class MathOperation {
	private String operation;

	public String getOperationNameNew() {
		if (this.operation.contains("+")) {
			return "addition";
		} else if (this.operation.contains("-")) {
			return "subtraction";
		} else {
			return "not detected";
		}
	}
}

A function with functional interface Function as input argument:

	List runOperationNameNew(List operationList, Function f) {
		List results = new ArrayList<>();
		for (MathOperation operation : operationList) {
			results.add(f.apply(operation));
		}
		return results;
	}

The lambda expression and Method Reference will be used:

		List list = new ArrayList();
		list.add(new MathOperation("+"));
		list.add(new MathOperation("-"));
		list.add(new MathOperation("*"));
		// lambda expression
		runOperationNameNew(list, operation -> operation.getOperationNameNew());
		// Method Reference
		runOperationNameNew(list, MathOperation::getOperationNameNew);
4. Reference to a constructor

we will replace a lambda expression:
(arguments) -> new ClassName(arguments)
with method reference:
ClassName::new
We have 2 constructor methods in MathOperation class:

public class MathOperation {
	private String operation;

	public MathOperation(String operation) {
		this.operation = operation;
	}

	public MathOperation() {
	}
}

Two Functions with functional interfaces Supplier and Function as input arguments to create new MathOperation in two ways (with and without input argument):

	MathOperation creatMathOperation(Supplier f) {
		return f.get();
	}
	
	MathOperation creatMathOperationNew(String operation, Function f) {
		return f.apply(operation);
	}

The lambda expression and Method Reference will be used:

		// constructor without input argument
		MathOperation mO1 = creatMathOperation(() -> new MathOperation());
		MathOperation mO2 = creatMathOperation(MathOperation::new);

		// constructor with input argument
		String oper = "-";
		MathOperation mO3 = creatMathOperationNew(oper, (s) -> new MathOperation(s));
		oper = "+";
		MathOperation mO4 = creatMathOperationNew(oper, MathOperation::new);
III. Source code

Technology:
– Java 8
– Eclipse Mars.1 Release (4.5.1)
methodreference
Run the source code above, we can see the results in Console Window:

=== static method ===
1 + 2 = 3
1 + 2 = 3
=== instance method of a particular object ===
addition
addition
=== instance method of an arbitrary object of a particular type ===
[addition, subtraction, not detected]
[addition, subtraction, not detected]
=== constructor ===
com.javasampleapproach.methodref.MathOperation@3b07d329
com.javasampleapproach.methodref.MathOperation@6d311334
=== constructor with argument ===
mO3.getOperation(): -
mO4.getOperation(): +


By grokonez | October 25, 2016.

Last updated on June 4, 2017.



Related Posts


Got Something To Say:

Your email address will not be published. Required fields are marked *

*