Java 8中Optional类型的有效用法

时间:2015-12-24 05:40:30

标签: java functional-programming java-8 monads optional

这是Java 8中可选类型的有效(预期)用法吗?

String process(String s) {
    return Optional.ofNullable(s).orElseGet(this::getDefault);
}

4 个答案:

答案 0 :(得分:20)

我将再次采取行动。

这是有效的用法吗?是的,从狭义上讲,它会编译并产生您期望的结果。

这是用途吗?不,现在,有时事情发现它们的用处超出了原来的范围,如果这样做有效,那就太好了。但对于"~/Scripts/jquery-ui-1.11.4/jquery-ui.js")); ,我们发现通常事情都不会很好。

Brian Goetz我在JavaOne 2015演讲中讨论了Optional的一些问题,使用Java 8 Lambdas和Streams进行的API设计

Optional的主要用途如下:(幻灯片36)

  

可选是为库方法返回类型提供有限机制,其中明确需要表示"没有结果,"使用Optional的地方绝大多数可能会导致错误

null链接方法的能力无疑是非常酷的,并且在某些情况下它减少了条件逻辑的混乱。但这常常没有成功。一个典型的代码味道,而不是使用方法链接到处理从某个方法返回的Optional的代码,它从某个方法创建 Optional这是可以为空的,以便链接方法并避免条件限制。这是一个实例的例子(也来自我们的演示文稿,幻灯片42):

Optional

使用// BAD String process(String s) { return Optional.ofNullable(s).orElseGet(this::getDefault); } // GOOD String process(String s) { return (s != null) ? s : getDefault(); } 的方法较长,大多数人发现它比传统代码更加模糊。不仅如此,它还没有充分的理由造成额外的垃圾。

底线:仅仅因为你可以做某事并不意味着你应该这样做。

答案 1 :(得分:6)

由于这或多或少是一个基于意见的问题,我会把我扔进去。如果你想说的话

if (id == 1) {
    Foo f = new Foo(id, "Bar", "US");
    return "Bar".equals(f.getName()) && "US".equals(f.getCountryCode());
} else {
    return false;
}
然后就这么说吧。使事物“功能化”不会自动使事情更清晰或更好。通过引入一个不必要的Optional,一对lambdas和一些我必须查找的Optional方法,您已经使代码更复杂且难以理解。我不认为Java的设计者“有意”让人们使用Optional来帮助使代码更加模糊。

编辑:在阅读了一些回复后,我认为值得添加一些评论。这不是我熟悉的函数式编程习惯,这将使其更难理解。我熟悉的习惯用法主要涉及Java流,或(在其他语言中)应用于数组或列表中的多个值或多个值的其他集合的功能习惯用法。在这些情况下,一旦你超越了陌生程度,功能语法就可以看作是一种改进,因为它允许隐藏一些细节(循环索引,迭代器,运行指针,累加器变量)。总的来说,它可以简化事情。这个例子本身并没有做任何这样的简化。

但是,某些Optional功能在流上下文中很有用。假设我们有一个parseInt()方法返回Optional<Integer>,如果输入字符串无效,则该方法为空。 (Java 8确实应该提供这个。)这样可以很容易地获取一个字符串数组并生成一个整数数组,其中不解析的字符串只是从结果中删除 - 使用parseInt在流map()中,并使用流过滤器过滤掉空Optional。 (我已经看到多个StackOverflow问题,询问如何执行此操作。)如果您只想保留正值,可以使用Optional.filter()将非存款更改为Optional.empty(),然后再使用流过滤器(虽然在这种情况下,您可以在之后添加另一个流过滤器,但在更复杂的情况下,Optional过滤器可能更有用)。从功能的角度来看,这就是Optional的主要好处。它允许您一次处理一组值,方法是为您提供一种表示“非值”的方法,并编写一个仍然可以使用它们的函数。所以我想除Optional的替换之外,null的主要用途是在整个序列作为一个整体应用函数时表示值序列中的空格。

答案 2 :(得分:4)

询问它是否有效&#34;是基于意见的,但至于它是否是预期的用例:不,它不是。

Oracle Java语言架构师Brian Goetz表示,Optional的用例适用于何时需要&#34;无价值&#34;标记,and when using null for this is likely to cause errors。具体来说,如果您的方法的合理用户不太可能考虑其结果为null的可能性,那么您应该使用Optional。它明确地旨在成为一般&#34;可能&#34;类型的对象,因为您在这里使用它。

在您的情况下,返回Optional的方法是private。这意味着它只能由班级的实施者使用,你可以假设他们对班级有很好的了解。方法 - 包括哪些方法可以返回null。由于没有合理的混淆风险,Brian Goetz(可能)会说他不会认为这是一个有效的用例。

答案 3 :(得分:2)

它有点做作,但有效&#39; (如语法和#39;),但正如@yshavit指出的那样,它的目的是用于图书馆开发。

之前的答案是由于FP代码难以阅读。下面是评论(有点详细,b / c是javadoc评论)但仍然。更容易阅读恕我直言。 (第二个是没有评论,至少是对齐以帮助提高可读性)

private boolean isFooValid(final Integer id) {
    return getFoo(id)
        // filter if 'f' matches the predicate, return Optional w/f if true, empty Optional if false
        .filter(f -> "Bar".equals(f.getName()) && "US".equals(f.getCountryCode())) 
        // If a value is present, apply the provided mapping function to it, 
        // If non-null, return an Optional describing the result.  
        .map(f -> true)
        // Return the value if present, otherwise return other.
        .orElse(false);
 }

或至少将其排成一行,以便更明显地发生了什么,更容易阅读。

private boolean isFooValid(final Integer id) {
    return getFoo(id)
        .filter(f -> "Bar".equals(f.getName()) && "US".equals(f.getCountryCode())) 
        .map(f -> true)
        .orElse(false);
 }