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
forEach
in the Arraylist observers
is not applicable to the type TemperatureObserver::react
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?
There are three kinds of method references that can be used when a single value is available from the stream:
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.
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
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);