Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Limitations of forEach with instance method references in Java 8

Tags:

Assume I have the following functional interface:

public interface TemperatureObserver {     void react(BigDecimal t); } 

and then in another class an already filled-in ArrayList of objects of type TemperatureObserver. Assuming that temp is a BigDecimal, I can invoke react in a loop using:

observers.forEach(item -> item.react(temp)); 

My question: can I use a method reference for the code above?

The following does not work:

observers.forEach(TemperatureObserver::react); 

The error message is telling me that

  1. forEach in the Arraylist observers is not applicable to the type TemperatureObserver::react
  2. TemperatureObserver does not define a method react(TemperatureObserver)

Fair enough, as forEach expects as an argument a Consumer<? super TemperatureObserver>, and my interface, although functional, does not comply to Consumer because of the different argument of react (a BigDecimal in my case).

So can this be solved, or it is a case in which a lambda does not have a corresponding method reference?

like image 918
Temp Agilist Avatar asked May 13 '17 20:05

Temp Agilist


People also ask

What is the advantage of using method reference in Java 8?

Java provides a new feature called method reference in Java 8. Method reference is used to refer method of functional interface. It is compact and easy form of lambda expression. Each time when you are using lambda expression to just referring a method, you can replace your lambda expression with method reference.

What is the purpose of forEach method of stream in Java 8?

The forEach method was introduced in Java 8. It provides programmers a new, concise way of iterating over a collection. The forEach method performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception.

What type referencing is allowed in Java 8?

There are several types of a method reference in Java that are allowed in Java 8. Reference to some static methods: The static methods in a code can be referred to from a class. Reference to some instance method of particular objects: Reference to some instance method of an arbitrary object of any particular type.

Why method reference is better than lambda?

The method references can only be used to replace a single method of the lambda expression. A code is more clear and short if one uses a lambda expression rather than using an anonymous class and one can use method reference rather than using a single function lambda expression to achieve the same.


1 Answers

There are three kinds of method references that can be used when a single value is available from the stream:

  1. A parameter-less method of the streamed object.

    class Observer {     public void act() {         // code here     } }  observers.forEach(Observer::act);  observers.forEach(obs -> obs.act()); // equivalent lambda 

    The streamed object becomes the this object of the method.

  2. A static method with the streamed object as parameter.

    class Other {     public static void act(Observer o) {         // code here     } }  observers.forEach(Other::act);  observers.forEach(obs -> Other.act(obs)); // equivalent lambda 
  3. A non-static method with the streamed object as parameter.

    class Other {     void act(Observer o); }  Other other = new Other(); observers.forEach(other::act);  observers.forEach(obs -> other.act(obs)); // equivalent lambda 

There is also a constructor reference, but that is not really relevant to this question.

Since you have an external value temp, and you want to use a method reference, you can do the third option:

class Temp {     private final BigDecimal temp;     public Temp(BigDecimal temp) {         this.temp = temp;     }     public void apply(TemperatureObserver observer) {         observer.react(this.temp);     } }  Temp tempObj = new Temp(temp);  observers.forEach(tempObj::apply); 
like image 123
Andreas Avatar answered Sep 23 '22 12:09

Andreas