Method References
1. What is a Method Reference
Lambda expressions are used to create anonymous methods. In cases when a lambda expression invokes only one existing method, it is better to refer to the existing method by name. Method references give the possibility to do this. They are compact lambda expressions for methods that already have a name.
For example, the next lambda expression calls only one method:
Consumer<String> consumer = str -> System.out.println(str);
It can be rewritten with method reference, which makes the code clearer:
Consumer<String> consumer = System.out::println;
There are four types of method references:
Type | Example |
---|---|
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::methodName |
Reference to a constructor | ClassName::new |
2. Reference to a Static Method
Syntax:
ContainingClass::staticMethodName
Let's refactor an example, where we are using a static method of a Boolean class:
Function<String, Boolean> function = e -> Boolean.valueOf(e);
System.out.println(function.apply("TRUE"));
With a method reference, the code looks like:
Function<String, Boolean> function = Boolean::valueOf;
System.out.println(function.apply("TRUE"));
3. Reference to an Instance Method of a Particular Object
Syntax:
containingObject::instanceMethodName
This type of method references is used when a lambda expression calls a method of an external object that already exists.
For example, let's refactor the example:
Consumer<String> consumer = e -> System.out.println(e);
consumer.accept("OCPJP 8");
Since System.out is an instance of type PrintStream, we can rewrite the previous example as:
Consumer<String> consumer = System.out::println;
consumer.accept("OCPJP 8");
Or let's look at another example:
Integer integer = new Integer(5);
Supplier<String> supplier = () -> integer.toString();
System.out.println(supplier.get());
After refactoring, the code will be:
Integer integer = new Integer(5);
Supplier<String> supplier = integer::toString;
System.out.println(supplier.get());
4. Reference to an Instance Method of an Arbitrary Object of a Particular Type
Syntax:
ContainingType::methodName
It is called a non-static method, but a class name is used for this type of method reference. Actually, the instance of the class is passed when the method is called.
Let's look at the lambda expression, where the non-static String.toLowerCase method is utilized:
Function<String, String> function = s -> s.toLowerCase();
System.out.println(function.apply("OCPJP 8"));
It can be refactored as:
Function<String, String> function = String::toLowerCase;
System.out.println(function.apply("OCPJP 8"));
5. Reference to a Constructor
Syntax:
ClassName::new
The ClassName shouldn't be the name of an abstract class or interface.
Let's refactor the example:
Function<String, Integer> function = (d) -> new Integer(d);
System.out.println(function.apply("4"));
The result is:
Function<String, Integer> function = Integer::new;
System.out.println(function.apply("4"));
The exact constructor isn't specified in a constructor reference expression. When a class declares multiple constructors, the compiler will check the type of the functional interface with all the constructors and choose the best match:
Function<String, Integer> function1 = (d) -> new Integer(d);
Function<Integer, Integer> function2 = (d) -> new Integer(d);
System.out.println(function1.apply("4"));
System.out.println(function2.apply(4));
Зарегистрируйтесь или войдите, чтобы иметь возможность оставить комментарий.