Tem*_*ist 20 java foreach java-8 method-reference
假设我有以下功能界面:
public interface TemperatureObserver {
void react(BigDecimal t);
}
Run Code Online (Sandbox Code Playgroud)
然后在另一个类中已经填充ArrayList了类型的对象TemperatureObserver.假设temp是a BigDecimal,我可以react使用以下命令在循环中调用:
observers.forEach(item -> item.react(temp));
Run Code Online (Sandbox Code Playgroud)
我的问题:我可以使用上面代码的方法参考吗?
以下不起作用:
observers.forEach(TemperatureObserver::react);
Run Code Online (Sandbox Code Playgroud)
错误消息告诉我
forEach在Arraylist observers该类型中不适用TemperatureObserver::reactTemperatureObserver 没有定义方法 react(TemperatureObserver)很公平,正如forEach预期的那样,作为一个参数a Consumer<? super TemperatureObserver>,我的界面尽管是功能性的,但Consumer由于react(BigDecimal在我的情况下)的不同参数而不符合.
那么这可以解决,还是一个lambda没有相应的方法参考的情况?
And*_*eas 21
当流中有单个值时,可以使用三种方法引用:
流式对象的无参数方法.
class Observer {
public void act() {
// code here
}
}
observers.forEach(Observer::act);
observers.forEach(obs -> obs.act()); // equivalent lambda
Run Code Online (Sandbox Code Playgroud)
流对象成为this该方法的对象.
以流对象作为参数的静态方法.
class Other {
public static void act(Observer o) {
// code here
}
}
observers.forEach(Other::act);
observers.forEach(obs -> Other.act(obs)); // equivalent lambda
Run Code Online (Sandbox Code Playgroud)以流对象作为参数的非静态方法.
class Other {
void act(Observer o);
}
Other other = new Other();
observers.forEach(other::act);
observers.forEach(obs -> other.act(obs)); // equivalent lambda
Run Code Online (Sandbox Code Playgroud)还有一个构造函数引用,但这与此问题并不真正相关.
由于您有外部值temp,并且想要使用方法引用,因此可以执行第三个选项:
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);
Run Code Online (Sandbox Code Playgroud)
请查看Java Tutorial中的Method References部分.它说:
有四种方法参考:
参考静态方法:
ContainingClass::staticMethodName引用特定对象的实例方法:
containingObject::instanceMethodName引用特定类型的任意对象的实例方法:
ContainingType::methodName对构造函数的引用:
ClassName::new
在那里它解释了ie TemperatureObserver::react将是第三种类型的方法引用:对特定类型的任意对象的实例方法的引用.在调用Stream.forEach方法的上下文中,该方法引用将等效于以下lambda表达式:
(TemperatureObserver item) -> item.react()
Run Code Online (Sandbox Code Playgroud)
要不就:
item -> item.react()
Run Code Online (Sandbox Code Playgroud)
哪个与您的void TemperatureObserver.react(BigDecimal t)方法签名不符.
正如您已经怀疑的那样,有些情况下您无法找到lambda的等效方法引用.Lambda更灵活,虽然恕我直言有时它们比方法参考更不易读(但这是一个品味的问题,很多人认为反过来).
仍然使用方法引用的方法是使用辅助方法:
public static <T, U> Consumer<? super T> consumingParam(
BiConsumer<? super T, ? super U> biConsumer,
U param) {
return t -> biConsumer.accept(t, param);
}
Run Code Online (Sandbox Code Playgroud)
你可以使用如下:
observers.forEach(consumingParam(TemperatureObserver::react, temp));
Run Code Online (Sandbox Code Playgroud)
但是,老实说,我更喜欢使用lambda.
它不起作用,因为您遍历处理程序而不是参数.
例如,此代码有效:
ArrayList<BigDecimal> temps = new ArrayList<>();
TemperatureObserver observer = new TemperatureObserverImpl();
temps.forEach(observer::react);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5392 次 |
| 最近记录: |