【问题标题】:Optional orElse throws NPE unexpectedly; taking null as a value可选的 orElse 意外抛出 NPE;取 null 作为值
【发布时间】:2018-11-22 10:51:20
【问题描述】:

功能:

private static void printArray(int[] array, Optional<Integer> startIndex, Optional<Integer> endIndex) {
    for(Integer i = a.orElse(new Integer(0)); i<=endIndex.orElse(new Integer(array.length));i++) {
        System.out.print(array[i]+"  ");
    }
}

在传递如下值时:

printArray(arr1, null, null);

NPE 被抛出。为什么Optional.orElse 函数没有创建一个新的 Integer 对象?我检查了 StackOverflow,但找不到来自 orElse 的 NPE 被抛出。我发现这种行为出乎意料。

欢迎所有建议。

【问题讨论】:

  • 我不太确定,但我认为使用Oprional 作为方法参数或方法返回是一种不好的做法。
  • 我不太明白为什么人们倾向于使用 lambda 表达式,即使是简单的任务。很多时候,它会降低代码的可读性和调试难度,就像这里一样。为什么不定义原始int 而不是可空的Integer
  • @Zorglube 实际上Optional 主要用作方法参数和返回值。如果没有,还有什么地方可以使用它?
  • @jediz 你在哪里看到 lambda 表达式?
  • @Zorglube:是的,将 Optionals 作为方法参数传递是丑陋的。 flatMap 使它变得不必要。

标签: java java-8 optional


【解决方案1】:

你应该传递Optional.empty()而不是null

printArray(arr1, Optional.empty(), Optional.empty());

如果你通过null,它会因为NPE而失败,因为你在null对象上调用orElse(可选在Java中没有特殊处理,它只是一个普通对象)。

附:使用OptionalInt 而不是Optional&lt;Integer&gt;

【讨论】:

    【解决方案2】:
    private static void printArray(int[] array, Optional<Integer> startIndex, Optional<Integer> endIndex) {
        int from = Optional.ofNullable(startIndex).orElse(Optional.of(0)).orElse(0);
        int to = Optional.ofNullable(endIndex).orElse(Optional.of(array.length)).orElse(array.length);
    
        for (int i = from; i <= to; i++) {
            System.out.print(array[i] + "  ");
        }
    }
    

    【讨论】:

    • 我已经尝试过了,它也可以,但这很复杂。感谢您的回答。
    • 这就是为什么你应该避免将可选参数作为参数传递给方法......或者为什么你应该避免将空值传递给方法......因为如果你这样做 -你违背了选项的全部目的。 KISS 原则。
    【解决方案3】:

    首先您不应该将 Optionals 作为参数传递给方法,如果您看到将 optionals 传递给方法的代码 - 更改它,在您调用方法的地方解开可选项。 考虑this cheat sheet from Zeroturnaround

    PS:只是为了好玩:我的建议是,如果您在这里使用可选项,那么为什么不使用流呢? :)

    public static void main(String[] args) {
        int[] array = new int[]{1, 2, 3, 4, 5};
    
        printArray(array, OptionalInt.of(0), OptionalInt.empty());
        System.out.println();
        printArray(array, OptionalInt.of(1), OptionalInt.empty());
        System.out.println();
        printArray(array, OptionalInt.of(1), OptionalInt.of(2));
        System.out.println();
    
    }
    
    private static void printArray(int[] array, OptionalInt startIndex, OptionalInt endIndex) {
        int startIdx = startIndex.orElse(0);
        int endIdx = endIndex.orElse(array.length);
    
        if (endIdx < startIdx)
            return;
    
        Arrays.stream(array).skip(startIdx).limit(endIdx).forEach(n -> System.out.print(n + " "));
    }
    

    它给了我们这个输出:

    1 2 3 4 5 
    2 3 4 5 
    2 3 
    

    【讨论】:

    • @NathanHughes “OP”是什么意思?
    • @Pavel 这根本不值得回答。请删除它。 OptionalInt 已在上一个答案中指出。另外,不要仅仅为了好玩而写答案。请转到适合它的社交平台。
    • @StutiVerma 你看...在java中将可选参数作为参数传递给方法 - 是代码气味的标志......并且是这样写的人的标志 - 不知道如何使用选项。所以我必须指出,无论你喜欢与否。我见过很多这样的代码,由来自阳光明媚的印度的亲爱的同事编写......
    猜你喜欢
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 2022-10-25
    • 2018-10-21
    • 2021-01-19
    • 2015-05-03
    • 1970-01-01
    相关资源
    最近更新 更多