Java处理if和new的不同方法

时间:2015-10-07 09:21:26

标签: java null

好的,我有一个关于处理空值的问题。这个问题可能在很大程度上基于意见,因此我将询问关于职业和利弊的问题。

假设我有一个可以返回null的函数,或者一个JSONArray。我总是想要一个JSONArray,所以如果函数的结果为null,我希望它创建一个空的。

目前我有以下方法:

jsonArray = jsonArray==null?new JSONArray():jsonArray;

我喜欢这种方法,因为它是一行,并且非常清楚它的作用。这确实引出了我的问题,这是否有效?我有一个想法,现在它将在不需要时执行jsonArray = jsonArray。虽然这似乎可以节省一次if (jsonArray == null)

的跳跃

处理空值的不同方法有哪些优点?

1 个答案:

答案 0 :(得分:10)

您是否看过Java 8的Optional课程?这是一个对象包装器,允许您以功能方式处理null。

例如,如果您希望方法public JSONArray getArray()始终返回null以外的其他内容,则可以使用您的代码。使用Optional,它将改为:

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

在jsonArray为null的情况下,可选项将为空;如果它不为null,它将包含jsonArray。

然后,您可以使用可选项指定的行为替换空检查。而不是

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

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

这意味着您不需要创建空的JSONArrays,列表,集合或字符串等等。如果包装对象实际为null,则从Optional.ofNullable返回singleton Optional,从而进一步减少开销。

如果您仍想采用经典方法,那也是可能的。由于if (option == null)应始终评估为false(如果您返回null而不是Optional,那么您会错过这一点!),您将使用if (option.isPresent())

如果您不使用Java 8,您可以编写自己的Optional或使用第三方库,例如Guava。

编辑:非Java 8解决方案

解决方案1 ​​

使用像番石榴这样的东西 - 看看http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Optional.html

解决方案2

自己写!在此实现中,SupplierConsumerPredicate是返回,接受或测试对象的接口。

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();
        }
    }
}