Java different approaches to handle if null then new

后端 未结 1 1776
半阙折子戏
半阙折子戏 2021-01-21 07:17

Okay, I\'ve got a question about handling nulls. This question can be heavily based upon opinion, therefore I\'m going to ask about pro\'s and cons.

Let\'s say I\'ve got

相关标签:
1条回答
  • 2021-01-21 07:19

    Have you taken a look at Java 8's Optional class? This is an object wrapper that lets you handle null in a functional way.

    For example, if you have a method public JSONArray getArray() that you want to always return something other than null, you can use your code. Using Optional, it would change to this:

    public Optional<JSONArray> getArray() {
        // jsonArray comes from somewhere
        return Optional.ofNullable(jsonArray);
    }
    

    In cases where jsonArray is null, the optional will be empty; in cases where it's not null, it will contain jsonArray.

    You can then replace null checks with behaviour dictated by the optional. Instead of

    JSONArray array = getArray();
    if (array != null) {
        // do something
    }
    

    you replace it with

    getArray().ifPresent(array -> // do something);
    

    This means you don't need to create empty JSONArrays, or Lists, or Sets, or Strings, or whatever. In cases where the wrapped object is actually null, a singleton Optional is returned from Optional.ofNullable, further reducing overhead.

    If you still want to take a classic approach, that's possible too. Since if (option == null) should always evaluate to false (if you return null instead of an Optional, you kind of miss the point!), you woud use if (option.isPresent()).

    If you're not using Java 8, you can either write your own Optional or use a third-party library such as Guava.

    EDIT: Non-Java 8 solutions

    Solution 1

    Use something like Guava - take a look at http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Optional.html

    Solution 2

    Write your own! In this implementation, Supplier, Consumer and Predicate are interfaces that return, accept or test an object.

    public abstract class Option<T> implements Iterable<T> {
    
        private static final Option NONE = new None();
    
        private Option() {
            // no-op
        }
    
        public static <T> Option<T> of(T t) {
            return t == null ? NONE : new Some<T>(t);
        }
    
        public static <T> Option<T> empty() {
            return NONE;
        }
    
        public abstract T get();
    
        public abstract T orElse(T fallback);
    
        public abstract T orElse(Supplier<T> supplier);
    
        public abstract <E extends Exception> T orThrow(Supplier<E> exceptionSupplier) throws E;
    
        public abstract boolean isPresent();
    
        public abstract Option<T> filter(Predicate<T> predicate);
    
        public abstract void ifPresent(Consumer<T> consumer);
    
        public abstract <O> Option<O> ifPresent(Function<T, O> function);
    
        private static final class Some<T> extends Option<T> {
    
            private final T value;
    
            private Some(final T value) {
                this.value = value;
            }
    
            @Override
            public T get() {
                return value;
            }
    
            @Override
            public T orElse(final T fallback) {
                return value;
            }
    
            @Override
            public T orElse(final Supplier<T> supplier) {
                return value;
            }
    
            @Override
            public <E extends Exception> T orThrow(final Supplier<E> exceptionSupplier) throws E {
                return value;
            }
    
            @Override
            public boolean isPresent() {
                return true;
            }
    
            @Override
            public Option<T> filter(final Predicate<T> predicate) {
                return predicate.test(value) ? this
                                             : NONE;
            }
    
            @Override
            public void ifPresent(final Consumer<T> consumer) {
                consumer.consume(value);
            }
    
            @Override
            public <O> Option<O> ifPresent(final Function<T, O> function) {
                return Option.of(function.apply(value));
            }
    
            @Override
            public Iterator<T> iterator() {
                return Collections.singletonList(value).iterator();
            }
        }
    
        private static final class None<T> extends Option<T> {
            @Override
            public T get() {
                throw new IllegalStateException("value not defined");
            }
    
            @Override
            public T orElse(final T fallback) {
                return fallback;
            }
    
            @Override
            public T orElse(final Supplier<T> supplier) {
                return supplier.get();
            }
    
            @Override
            public <E extends Exception> T orThrow(final Supplier<E> exceptionSupplier) throws E {
                throw exceptionSupplier.get();
            }
    
            @Override
            public boolean isPresent() {
                return false;
            }
    
            @Override
            public Option<T> filter(final Predicate<T> predicate) {
                return this;
            }
    
            @Override
            public void ifPresent(final Consumer<T> consumer) {
                // no-op
            }
    
            @Override
            public <O> Option<O> ifPresent(final Function<T, O> function) {
                return NONE;
            }
    
            @Override
            public Iterator<T> iterator() {
                return Collections.<T>emptyList().iterator();
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题