我有一个mutator方法,它只设置参数中提供的非空字段。该参数返回裸引用,而不是Optional
包装器,并且无法更改。
在Java 8之前,一种方法是:
Double h = arg.getH();
if ( null != h ) setH( h );
Double v = arg.getV();
if ( null != h ) setV( v );
String s = arg.getS();
if ( null != s ) setS( s );
// Etc. ...
从Java 8开始,可以通过一次性Optional
更简洁地表达这一点。
Optional.ofNullable( arg.getH()).ifPresent( this::setH );
Optional.ofNullable( arg.getV()).ifPresent( this::setV );
Optional.ofNullable( arg.getS()).ifPresent( this::setS );
// Etc. ...
这个成语不太熟悉。但是,它也消除了潜在的错误来源 - 例如在Java 8"之前的错误。上面的代码。
问题:频繁使用这种新模式是否有任何负面影响?(例如,它与编译大小或性能的早期模式相比如何? )
答案 0 :(得分:5)
显然,您的任务是调整类型实例以反映控件之外的类型的属性。 (我有点担心// etc
评论。)在这种情况下,我们可以将“转移此属性,如果不是null
”封装为它自己的操作:
// in MyType
static <T> BiConsumer<TypeOfArg,MyType> transfer(
Function<TypeOfArg,T> from, BiConsumer<MyType,T> to) {
return (arg,myself) -> {
T value = from.apply(arg);
if(value!=null) to.accept(myself, value);
};
}
static final BiConsumer<TypeOfArg,MyType> TRANSFER_ALL_PROPERTIES =
transfer(TypeOfArg::getH, MyType::setH).andThen(
transfer(TypeOfArg::getV, MyType::setV).andThen(
transfer(TypeOfArg::getS, MyType::setS)));
void mutatorMethod(TypeOfArg arg) {
TRANSFER_ALL_PROPERTIES.accept(arg, this);
}
我很确定,这也可能会导致争论这是否比第一个变体中的get
- if
- set
调用的普通序列更好,但是我认为,这与熟悉度有很大关系。
对我来说,transfer(TypeOfArg::getV, MyType::setV)
表达的意图比Optional.ofNullable( arg.getV()).ifPresent( this::setV )
更好,这仍然非常像命令性陈述。
对于那些担心临时对象的人,代码不会创建任何。
答案 1 :(得分:0)
以通用方式回答性能总是很棘手。事实是:JVM做了很多优化,很难说它对你的应用程序的行为如何。即便如此,随着时间的推移,性能可能会与在'冷启动'之后测量的性能不同。例如,如果您的参数在99%的时间内都不为空,则分支预测可能会使两个变体的性能无关紧要。
最后,如果您真的关心性能,请在您自己的应用程序上进行测量。
总而言之,我说选择您更喜欢阅读和维护的版本会更好。就我而言,Java 8之前会赢,但那只是我:)