![]() | |
|
Method references can be seen as shorthand for lambdas calling only a specific method. The basic idea is that if a lambda represents "call this method directly". It is best to refer to the method by name rather than by a description of how to call it. A method reference lets you create a lambda expression from an existing method implementation. By referring to a method name explicitly, your code can gain better readability.
![]() | |
Lambdas created from constructors are often referred to as constructor references, which are considered for exam to be a subset of method references. |
When you need a method reference, the target reference is placed before the delimiter ::
and the
name of the method is provided after it. For example, String::toUpperCase
is a method reference to
the method toUpperCase
defined in the String
class. The method reference is shorthand
for the lambda expression (String s) -> s.toUpperCase();
.
![]() | |
Remember that no parentheses (round brackets) are needed because you are not actually calling the method. |
There are four types of method reference:
Reference to a static method
A non-constructor method reference consists of a qualifier, followed by the ::
delimiter, followed by an identifier.
The qualifier is a type for static methods.
Syntax:
Class::staticMethodName
Refactoring example:
IntFunction<String> f1 = (i) -> String.valueOf(i); System.out.println(f1.apply(100));
As you can see in the following code, we made reference to valueOf
static method in String
class:
IntFunction<String> f1 = String::valueOf; System.out.println(f1.apply(100));
In this case, the method reference is equivalent to a lambda expression that supplies the parameters of the method.
Reference to a constructor
A constructor reference consists of a qualifier, followed by the ::
delimiter, followed by the keyword
new
. The qualifier type must support the creation of instances; for example, it cannot be the name of an
abstract class or interface.
Syntax:
ClassName::new
Refactoring example:
Function<char[], String> f1 = (arr) -> new String(arr); System.out.println(f1.apply(new char[] {'H', 'i'}));
Constructor reference expression String::new
equates to lambda expression (char[] arr) -> new String(arr)
. A
lambda for instantiating String
is assigned to Function
. The subsequent
Function.apply(...)
expression executes this lambda, returning the String
instance.
Function<char[], String> f1 = String::new; System.out.println(f1.apply(new char[] {'H', 'i'}));
In a constructor reference expression, you do not specify the exact constructor. Instead, you simply write ::new
. When
a class declares multiple constructors, the compiler will check the type of the functional interface with all of the constructors
and choose the best match.
// Java compiler infers the right constructor to call based // on the context in which the constructor reference appears Function<char[], String> f1 = String::new; Function<StringBuffer, String> f2 = String::new; System.out.println(f1.apply(new char[] {'H', 'i'})); System.out.println(f2.apply(new StringBuffer().append("Hello")));
Reference to an instance method of an arbitrary object of a particular type
Syntax:
Class::instanceMethodName
Reference to an instance method of an arbitrary object of a particular type refers to a non-static method that is not bound
to a receiver. For example, String::trim
is a non-static method reference that identifies the non-
static trim()
method of the String class
. Because a non-static method requires a target
object, which in this example is a String
object, trim()
will be invoked on this object.
![]() | |
This can be a little confusing. So we are calling a non-static method but using a class name. Actually the instance of the class is passed when the method is called. |
String::trim
is equivalent to lambda (String str) -> { return str.trim(); }
.
In this type of method references, the first parameter becomes the target of the method. For example,
String::compareToIgnoreCase
is the same as (x, y) -> x.compareToIgnoreCase(y)
.
Refactoring example:
BiFunction<String, String, Boolean> f1 = (s1, s2) -> s1.equalsIgnoreCase(s2); System.out.println(f1.apply("Hello", "HELLO"));
BiFunction<String, String, Boolean> f1 = String::equalsIgnoreCase; System.out.println(f1.apply("Hello", "HELLO"));
Reference to an instance method of a particular object
Syntax:
object::instanceMethodName
Reference to an instance method of a particular object refers to a non-static method that is bound to a receiver.
For example, System.out::printf
is a non-static method reference that identifies the printf(String format, Object args...)
method of the java.io.PrintStream
class. This method is bound to the System.out
(standard output stream) object
(the receiver) and will be invoked on this object. System.out::printf
is equivalent to this lambda:
(String fmt, Object... args) -> System.out.printf(fmt, args);
![]() | |
This kind of method references refers to a situation when you are calling a method in a lambda to an external
object that already exists. For example, the lambda expression |
Refactoring example:
Integer i = new Integer(1); Supplier<String> f1 = () -> i.toString(); System.out.println(f1.get());
Integer i = new Integer(1); Supplier<String> f1 = i::toString; System.out.println(f1.get());
![]() ![]() ![]() |