Java 8: Difference Between Bound Receiver Method Link and UnBound Receiver Method

I am trying to use Java 8 method references in my code. There are four types of method references.

  1. Link to the static method.
  2. Instance Method (Associated Recipient).
  3. Instance Method (UnBound Recipient).
  4. Designer reference.

I have no problems with the Static method reference and Constructor reference , but the Instance Method (Bound receiver) and Instance Method (UnBound receiver) really confused me. In the Bound receiver, we use the reference variable Object to call a method similar to the following:

 objectRef::Instance Method 

In the UnBound receiver UnBound we use the class name to call a method similar to the following:

 ClassName::Instance Method. 

I have the following question:

  1. Why do we need different types of method references for instance methods?
  2. What is the difference between references to Bound and Unbound receiver methods?
  3. Where should we use the Bound receiver and where should we use the Unbound receiver?

I also found an explanation of the Bound and Unbound recipient from books on Java 8 language features , but was still unaware of the actual concept.

+10
source share
6 answers

The idea behind an unBound receiver, such as String::length , is that you reference a method to an object that will be supplied as one of the lambda parameters . For example, a lambda expression (String s) -> s.toUpperCase() can be rewritten as String::toUpperCase .

But Bounded refers to a situation where you call a method in lambda for an external object that already exists . For example, lambda expression () -> expensiveTransaction.getValue() can be rewritten as expensiveTransaction::getValue .

Situations for three different ways to refer to a method

(args) -> ClassName.staticMethod(args) can be ClassName::staticMethod

(arg0, rest) -> arg0.instanceMethod(rest) can be ClassName::instanceMethod ( arg0 is of type ClassName )

(args) -> expr.instanceMethod(args) can be expr::instanceMethod

Answer removed from Java 8 in action book

+18
source

In principle, unbound receivers allow you to use instance methods as if they were static methods with the first parameter of the declaration type, so you can use them as functions, passing in any instance that you want. With the associated receiver, an instance of "target" is actually part of the function.

An example might make this clearer:

 import java.util.function.*; public class Test { private final String name; public Test(String name) { this.name = name; } public static void main(String[] args) { Test t1 = new Test("t1"); Test t2 = new Test("t2"); Supplier<String> supplier = t2::method; Function<Test, String> function = Test::method; // No need to say which instance to call it on - // the supplier is bound to t2 System.out.println(supplier.get()); // The function is unbound, so you need to specify // which instance to call it on System.out.println(function.apply(t1)); System.out.println(function.apply(t2)); } public String method() { return name; } } 
+10
source

If you want a method to be executed for a specific instance of a class, you use a linked receiver.

For instance:

 Stream.of("x","y").forEach(System.out::println); 

will execute println in a separate instance of PrintStream - an instance of System.out . Therefore, System.out.println("x") and System.out.println("y") will execute as a result of passing this method reference to forEach .

On the other hand, if you want the method to execute on an unspecified instance of the class, you can use an unbound receiver.

For instance:

 Stream.of("x","y","").filter(String::isEmpty); 

will execute isEmpty() on each of the stream's String instances: I am "x".isEmpty() , "y".isEmpty() and "".isEmpty() .

+3
source

Along with great answers from above. Thanks to a wonderful explanation by Joshua Bloch, an effective third edition of java. Finally, I was able to wrap my head around what a limited and unlimited link means.

In the restricted reference, the receiving object is indicated in the reference to the method. Related links are similar in nature to static links: a function object takes the same arguments as a reference method.

In unrelated links, the receiving object is indicated when applying the functional object through an additional parameter before the declared method parameters. Unlimited links are often used as display and filter functions in stream pipelines.

Finally, there are two types of constructor references for classes and arrays. References to designers serve as factory objects.

 'Method Ref | Example | Lambda Equivalent Static | Integer::parseInt | str -> Integer.parseInt(str) Bound | Instant.now()::isAfter | Instant then = Instant.now(); | t -> then.isAfter(t) Unbound | String::toLowerCase | str -> str.toLowerCase() Class Constructor | TreeMap<K,V>::new | () -> new TreeMap Array Constructor | int[]::new | len -> new int[len]' 
0
source

I took this from a recent presentation

enter image description here

0
source

Here is an example:

 public static void main(String[] args) { // unbound UnaryOperator<String> u = String::toUpperCase; System.out.println(u.apply("hello")); // bound String a = "hello"; Supplier<String> r = a::toUpperCase; System.out.println(r.get()); } 

which will print two lines of HELLO .

0
source

Source: https://habr.com/ru/post/1244814/


All Articles