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

空安全方法链接(可选)

范楚
2023-03-14

番石榴的可选模式很棒,因为它有助于用null消除歧义。当链的第一部分可能不存在时,转换方法非常有助于创建空安全方法链,但当链的其他部分不存在时则不有用。

这个问题与Guava可选类型有关,当转换返回另一个可选时,它会问本质上相同的问题,但对于不同的用例,我认为这可能不是可选的预期用途(处理错误)。

考虑一个方法<代码>可选

在中间方法可能返回null/缺席()的常见情况下,似乎没有一种优雅的方法来链接调用。例如,假设Book有一个方法可选

它似乎是相当合理的,有一个转换()类方法可选将接受一个函数返回可选。它的行为与当前实现完全相同,只是它不会将函数的结果包装在可选项中。实现(对于Present)可能为:

public abstract <V> Optional<V> optionalTransform(Function<? super T, Optional<V>> function) {
    return function.apply(reference);
}

不存在的实现与转换相同:

public abstract <V> Optional<V> optionalTransform(Function<? super T, Optional<V>> function) {
    checkNotNull(function);
    return Optional.absent();
}

如果有一种方法来处理返回null的方法,而不是用于处理遗留对象的可选,那也很好。这样的方法类似于转换,但只需在函数的结果上调用Optional.fromNullable

我很好奇是否有其他人遇到过这种麻烦,并找到了很好的解决方法(不涉及编写自己的可选类)。我也很想听到番石榴团队的消息,或者被指给我与这个问题相关的讨论(我在搜索中没有找到任何)。


共有2个答案

虞滨海
2023-03-14

您可能已经知道了,但是您可以添加。或者(可选。不存在)在每次转换后返回可选(在您的情况下是在.transform(Book.getPublisher)之后)减少可选

Optional<List<Book>> publishedBooks = findBook(id).transform(Book.getPublisher).
        or(Optional.absent()).transform(Publisher.getPublishedBooks);

不幸的是,的类型是可选的。此处无法推断缺席,因此代码实际上变成:

Optional<List<Book>> publishedBooks = book.transform(Book.getPublisher).
        or(Optional.<Publisher> absent()).transform(Publisher.getPublishedBoooks);

不太方便,但似乎没有其他办法。

晋弘义
2023-03-14

你正在寻找一些单子,但番石榴的可选(相反,例如斯卡拉的选项)只是一个函数。

函数到底是什么?!

函子和单子是一种盒子,一种包装某些值的上下文。包含某种类型A值的函子知道如何应用函数A=

蒙纳。。什么

Monad几乎与Functor相同,只是它使用Monad(A)中包装的函数返回值=

在这里,您可以找到对基本FP术语的非常棒的解释:http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html

函子

Java8的可选选项可以分为函数(http://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#map-java.util.function.Function-)和单子(http://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#flatMap-java.util.function.Function-)。

很好,玛辛,但我该如何解决我的特殊问题呢?

我目前正在从事一个使用Java6的项目,昨天我编写了一个名为“Optionals”的助手类,这为我节省了很多时间。

它提供了一些辅助方法,允许我将可选的转换为monad(flatMap)。

代码如下:https://gist.github.com/mkubala/046ae20946411f80ac52

因为我的项目的代码库仍然使用null作为返回值,所以我引入了Optionals。lift(函数),可用于将结果包装到可选文件中。

为什么起重结果变成可选?为了避免传递到transform中的函数可能返回null,而整个表达式将返回“present of null”(顺便说一句,这在Guava的Optional中是不可能的,因为这个后置条件-

几个例子

让我们假设findEntity()返回可选的和Entity.getDecimalField(...)可能返回BigDecimal或null:

Optional<BigDecimal> maybeDecimalValue = Optionals.flatMap(
    findEntity(),
    new Function<Entity, Optional<BigDecimal>> () {
        @Override 
        public Optional<BigDecimal> apply(Entity input) {
            return Optional.fromNullable(input.getDecimalField(..));
        }
    }
);

还有一个例子,假设我已经有了一些函数,它从实体中提取十进制值,并可能返回空值:

Function<Entity, Decimal> extractDecimal = .. // extracts decimal value or null
Optional<BigDecimal> maybeDecimalValue = Optionals.flatMap(
    findEntity(),
    Optionals.lift(extractDecimal)
);

最后,但并非最不重要——以您的用例为例:

Optional<Publisher> maybePublisher = Optionals.flatMap(findBook(id), Optionals.lift(Book.getPublisher));

// Assuming that getPublishedBooks may return null..
Optional<List<Book>> maybePublishedBooks = Optionals.flatMap(maybePublisher, Optionals.lift(Publisher.getPublishedBooks));

// ..or simpler, in case when getPublishedBooks never returns null
Optional<List<Book>> maybePublishedBooks2 = maybePublisher.transform(Publisher.getPublishedBooks);

// as a one-liner:
Optionals.flatMap(maybePublisher, Optionals.lift(Publisher.getPublishedBooks)).transform(Publisher.getPublishedBooks);
 类似资料:
  • 从2.0版本开始Spring Security 改进了对服务层方法的安全支持,它提供了对JSR-250注解安全支持以及框架的原生@Secured注解的支持。从3.0开始你也可以使用新的基于表达式的注解。你可以将安全应用到单个bean.使用intercept-methods元素装饰Bean的声明。或者你可以在使用AspectJ风格的切入点应用安全到整个服务层的多个Bean类。 <global-met

  • 问题内容: 我想像这样的代码来获取有关Java7功能的详细信息 可以做这样的事情 但坦白说对我来说还不太清楚。请解释一下? 问题答案: Null-safe方法调用是针对Java 7提出的,作为Project Coin的一部分,但并未最终发布。 在此处查看所有建议的功能以及所有最终选择的功能-https: //wikis.oracle.com/display/ProjectCoin/2009Prop

  • 我正在寻找一种技术来从添加到Opportunity对象的自定义按钮执行Apex代码,以保护用户免受CSRF的影响。 当前使用的方法来自“问题-自定义”按钮或指向带有自定义控制器的Visualforce页面的链接。本质上: 有一个商机自定义按钮,内容源设置为“VisualForce Page”。 此按钮的内容设置为使用standardController的Opportance的Visualforce

  • 我已经使用空手道6个月了,我真的对它提供的功能印象深刻。我知道空手道是为了单独测试API,但我们也试图将它用于E2E测试,这涉及到一步一步地调用多个场景。我们的功能文件如下1。调用功能1:Scenario1 2。调用功能2:Scenario2....注意:我们正在重新使用一个用于API测试和E2E测试的场景,有时我发现很难记住所有的特性文件。我们是否可以像java那样链式调用场景,我怀疑特性文件会

  • 我有一个方法,它将和作为参数,查询数据库,并实现一些逻辑,以逗号分隔的字符串查找该可以访问的URL。 我想开发此方法的空安全版本,使用相同的和作为参数,然后返回一个,如果传递给它的值中至少有一个为空或方法返回,则该值将为空。我写了下面的代码,但它看起来像是一个基于空检查的实现,我看不到使用Optional使代码更简洁的好处。 有没有更好的方法让代码更具可读性?

  • 我尝试使用功能,如可选链接、空合并。但是在传输时给了我一个错误。