将 get/test/set of 裸引用替换为 Optional.ofNullable(..).ifPresent(.



>我有一个突变器方法,它只设置参数中提供的非空字段。该参数返回裸引用,而不是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之前"代码中的错误。

问:频繁使用这种较新的模式是否有任何负面影响? (例如,它在编译大小或性能方面与早期模式相比如何?

显然,您的任务是调整类型的实例以反映控件之外的类型的属性。(我有点担心// 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 )更好地表达意图,这读起来仍然很像命令式陈述。

对于那些关心临时对象的人来说,代码不会创建任何对象。

性能总是很难以通用方式回答。事实是:JVM进行了如此多的优化,以至于很难说它将如何为您的应用程序运行。即便如此,随着时间的推移,性能也可能与"冷启动"后立即测量的性能不同。例如,如果您的参数在 99% 的时间内不为空,则分支预测可能会使两个变体的性能变得不显著。

最后,如果您真的关心性能,请在您自己的应用程序上进行测量。

总而言之,我想说的是,最好选择您更习惯阅读和维护的版本。就我而言,Java 8 之前的版本会赢,但这只是我:)

最新更新