当前位置: 首页 > 知识库问答 >
问题:

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

陈寒
2023-03-14

我有一个mutator方法,它只设置参数中提供的非null字段。参数返回裸引用,而不是可选的包装器,并且不能更改。

在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. ...

从Java8开始,可以使用一次性的可选的更简洁地表达这一点。

Optional.ofNullable( arg.getH()).ifPresent( this::setH );
Optional.ofNullable( arg.getV()).ifPresent( this::setV );
Optional.ofNullable( arg.getS()).ifPresent( this::setS );
// Etc. ...

这个成语不太熟悉。然而,它也消除了一个潜在的错误源——比如上面“Java8之前”代码中的错误。

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


共有2个答案

姜兴业
2023-03-14

用一般的方式回答性能问题总是很棘手的。事实是:JVM进行了太多优化,很难说它将如何为您的应用程序运行。即使如此,随着时间的推移,性能也可能与“冷启动”后测量的性能不同。例如,如果您的参数99%的时间不为null,则分支预测可能会使这两个变量的性能变得无关紧要。

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

总而言之,我想说的是,最好选择您在阅读和维护方面更舒适的版本。在我的例子中,前Java 8将获胜,但那只是我:)

太叔景同
2023-03-14

显然,您的任务是调整类型的实例以反映您无法控制的类型的属性。(我有点担心//etc的评论。)在这种情况下,我们可以将“transfer this property,if notnull”封装为一个单独的操作:

// 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),读起来仍然很像命令语句。

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

 类似资料:
  • 我最近看到一篇博客文章(由@java发布),它暗示下面的代码正在变得越来越普遍: 而不是: 在这种情况下,Optional的使用对我来说似乎非常尴尬,甚至忽略了变量的命名--后者更容易阅读,对于用例来说也更习惯(处理空值)。我相信这也能更好地捕获语义--我的代码可能不符合Optional试图捕获的语义(如本文和Oracle文章所述)。 我看不出来,但是有没有一个好的语义原因来偏好Optional.

  • 我刚从Java7转到8,我的代码中到处都是代码片段,比如 我注意到,空检查有时被认为是一种反模式,而Java8提倡使用可选的。让我的代码看起来像这样有什么好处吗

  • 在PyCharm中,当我写道: 它说“Function call can be replacement with set literal”,所以它将它替换为: 这是为什么?Python中的与字典不同? 如果它想优化这个,为什么这个更有效?

  • 问题内容: 我有一个字符串,例如。我想分别使用 JavaScript*和分别替换两个下划线。(因此)输出看起来像。该字符串可能包含多对下划线。 * 我所寻找的是一个方法来 无论是 运行在每场比赛,红宝石做它的方式的函数: 或 能够再次引用匹配的组,就像在ruby中一样: 有什么想法或建议吗? 问题答案: 哦,或者您也可以:

  • 目前,我们正在使用一个遗留应用程序,其中Java HttpServletRequest。GetSession()函数,用于从客户端浏览器获取会话,其中会话是从浏览器的父选项卡设置的。 现在,我们需要使用具有解耦微服务架构(UI React JS)的新应用程序访问相同的会话信息[例如,会话中有令牌]。我们是否能够从前端访问会话? 感谢您的建议。 非常感谢。

  • 问题内容: 如何使用PHP 用(我认为其称为单引号)替换(我认为它称为双引号)? 问题答案: 或重新分配