【问题标题】:Optional<> and return type narrowing可选<>和返回类型缩小
【发布时间】:2015-07-04 08:38:23
【问题描述】:

在 Java

class A {}
class B extends A {}
interface Sup { A a(); /* returns A instance, or null */ }
interface Sub extends Sup { B a(); }

在 Java 8 中,如果我想让我的 API“更安全”,我应该返回 Optional&lt;A&gt; 而不是“原始”A

interface Sup { Optional<A> a(); }
interface Sub extends Sup { Optional<B> a(); }

但不编译!因为Optional&lt;B&gt; 不是Optional&lt;A&gt; 的子类。

我应该如何解决这个问题?

【问题讨论】:

    标签: java optional narrowing


    【解决方案1】:

    您可以使用通配符。

    interface Sup { Optional<? extends A> a(); }
    
    interface Sub extends Sup { Optional<? extends B> a(); }
    

    我本可以只使用Optional&lt;B&gt;,但使用Optional&lt;? extends B&gt; 允许另一个接口扩展Sub 并做同样的事情。

    就个人而言,我认为这有点混乱,最好在必要时返回ABnull

    【讨论】:

    • schools of thought 认为转向Optional 范式会产生更少的NPE,并迫使人们更好地推理代码实际具有的行为。
    • @Makoto 我知道这些论点,并且我同意它们(我一直使用Optional)。我最后的评论是关于结合 ?Optional
    • 使用上限并不是最糟糕的事情;关于为什么要这样做,可能有非常正当的理由。我之所以这样反应,是因为你提到了null
    • @Makoto 你永远不会回来null?
    • 虽然我认为这有点太啰嗦了,但我不会返回 null 我可以提供帮助的地方 - 我可以使用 Optional,无论是使用 Guava 还是使用 Java 8、我选择使用这种模式而不是null
    【解决方案2】:

    更改您的父边界以使用通配符:

    Optional<? extends A> // parent
    Optional<? extends B> // child
    

    您的代码现在不起作用的原因是泛型是不变的。 BA,但 Optional&lt;B&gt; 不是 Optional&lt;A&gt;

    【讨论】:

      猜你喜欢
      • 2019-09-09
      • 2023-02-14
      • 2019-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-27
      • 2020-09-14
      相关资源
      最近更新 更多