我正在使用lamdbas,所以我可以根据我可以从三个不同对象检索的值一致地设置ModelObject的属性。代码的工作原理如下:
public class Processor {
private void bar(Setter setter, MyClass myObject) {
String variable = myObject.getStringByABunchOfMethods();
setter.setVariable(variable);
}
protected void foo(...) {
...
bar(value -> model.setA(CONSTANT, value), aObject);
bar(value -> model.setB(value), bObject);
bar(value -> model.setC(value), cObject);
...
}
private interface Setter {
public void setVariable(String string);
}
}
public interface IModel {
public void setA(String arg0, String arg1);
public void setB(String arg0);
public void setC(String arg0);
}
我已阅读here,可以将bar(value -> model.setB(value), bObject);
重写为bar(model::setB, bObject)
。我认为这看起来更好,更简洁,但我还没有找到将setA
方法重写为double :: notation的方法。任何人都可以告诉我这是否可行,如果可以的话:这怎么可能?
答案 0 :(得分:5)
来自https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html和https://www.codementor.io/eh3rrera/tutorials/using-java-8-method-reference-du10866vx
将有4种不同的方法参考。相应的lambda和方法参考:
lambda 值 - > model.setA(CONSTANT,value)与上面的任何lambda不对应,因此无法将其重写为方法引用。
答案 1 :(得分:4)
要使用双冒号表示法,您引用的方法必须与所需方法具有相同的签名。因此,除非您更改::
:
IModel
您可以在setA
中添加IModel
的重载:
default void setA(String arg0) {
setA(CONSTANT, arg0);
}
然后,您可以引用该重载:
bar(model::setA, aObject);
答案 2 :(得分:3)
您不需要特殊界面:setB
是Consumer<String>
而setA
是BiConsumer<String, String>
。然后,您可以将BiConsumer
调整为Consumer
:
使用界面中的默认方法(如果始终使用常量调用setA
,为什么不呢?):
interface Model {
public void setA(String arg0, String arg1);
default void setA(String arg1) {setA(CONSTANT, arg1);}
public void setB(String arg0);
public void setC(String arg0);
}
使用BiConsumer
到Consumer
的适配器:
static <T, U> Consumer<V> adapt(T t, BiConsumer<T, U> biConsumer) {
Objects.requireNonNull(biConsumer, "biConsumer");
Objects.requireNonNull(t, "t");
return t -> biConsummer.accept(t, u);
}
并像这样使用它:
protected void foo(...) {
...
bar(adapt(CONSTANT, model::setA), aObject);
bar(model::setB, bObject);
bar(model::setC, cObject);
...
}
注意:我使用adapt
作为示例名称,但当您将其与其他adapt
重载方法混合时,这是一个糟糕的名称(因为通用和类型擦除)。我个人将其命名为fixLeftValue
。
请注意,每次调用adapt
时都会生成foo
。
答案 3 :(得分:2)
不是编写Setter
功能接口的方式。与setB
和setC
不同,setA
方法需要两个参数,而接口Setter
的方法只需要一个参数。您可以添加另一个接受两个参数的接口:
private interface SetterWithDefault {
public void setVariable(String defaultString, String string);
}
然后您可以通过bar
方法调用它:
private void bar(SetterWithDefault setter, String defaultString, MyClass myObject) {
String variable = myObject.getStringByABunchOfMethods();
setter.setVariable(defaultString, variable);
}
然后您可以按如下方式致电bar
:
bar(model::setA, CONSTANT, aObject);
注意:您可以保留其他bar
方法。新的可能是一个过载。