用Optional.ofNullable(...)替换get / test / set裸引用.ifPresent(...)?

时间:2016-06-08 15:50:48

标签: java java-8 optional

我有一个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"之前的错误。上面的代码。

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

2 个答案:

答案 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之前会赢,但那只是我:)