Why should Java 8's Optional not be used in arguments

前端 未结 20 1880
我寻月下人不归
我寻月下人不归 2020-11-22 11:33

I\'ve read on many Web sites Optional should be used as a return type only, and not used in method arguments. I\'m struggling to find a logical reason why. For example I h

20条回答
  •  故里飘歌
    2020-11-22 12:19

    First of all, if you're using method 3, you can replace those last 14 lines of code with this:

    int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));

    The four variations you wrote are convenience methods. You should only use them when they're more convenient. That's also the best approach. That way, the API is very clear which members are necessary and which aren't. If you don't want to write four methods, you can clarify things by how you name your parameters:

    public int calculateSomething(String p1OrNull, BigDecimal p2OrNull)

    This way, it's clear that null values are allowed.

    Your use of p1.orElse(null) illustrates how verbose our code gets when using Optional, which is part of why I avoid it. Optional was written for functional programming. Streams need it. Your methods should probably never return Optional unless it's necessary to use them in functional programming. There are methods, like Optional.flatMap() method, that requires a reference to a function that returns Optional. Here's its signature:

    public Optional flatMap(Function> mapper)

    So that's usually the only good reason for writing a method that returns Optional. But even there, it can be avoided. You can pass a getter that doesn't return Optional to a method like flatMap(), by wrapping it in a another method that converts the function to the right type. The wrapper method looks like this:

    public static  Function> optFun(Function function) {
        return t -> Optional.ofNullable(function.apply(t));
    }
    

    So suppose you have a getter like this: String getName()

    You can't pass it to flatMap like this:

    opt.flatMap(Widget::getName) // Won't work!

    But you can pass it like this:

    opt.flatMap(optFun(Widget::getName)) // Works great!

    Outside of functional programming, Optionals should be avoided.

    Brian Goetz said it best when he said this:

    The reason Optional was added to Java is because this:

    return Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
        .stream()
        .filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
        .filter(m ->  Arrays.equals(m.getParameterTypes(), parameterClasses))
        .filter(m -> Objects.equals(m.getReturnType(), returnType))
        .findFirst()
        .getOrThrow(() -> new InternalError(...));
    

    is cleaner than this:

    Method matching =
        Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
        .stream()
        .filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
        .filter(m ->  Arrays.equals(m.getParameterTypes(), parameterClasses))
        .filter(m -> Objects.equals(m.getReturnType(), returnType))
        .getFirst();
    if (matching == null)
      throw new InternalError("Enclosing method not found");
    return matching;
    

提交回复
热议问题