好的,我有一个关于处理空值的问题。这个问题可能在很大程度上基于意见,因此我将询问关于职业和利弊的问题。
假设我有一个可以返回null的函数,或者一个JSONArray。我总是想要一个JSONArray,所以如果函数的结果为null,我希望它创建一个空的。
目前我有以下方法:
jsonArray = jsonArray==null?new JSONArray():jsonArray;
我喜欢这种方法,因为它是一行,并且非常清楚它的作用。这确实引出了我的问题,这是否有效?我有一个想法,现在它将在不需要时执行jsonArray = jsonArray
。虽然这似乎可以节省一次if (jsonArray == null)
处理空值的不同方法有哪些优点?
答案 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解决方案
使用像番石榴这样的东西 - 看看http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Optional.html
自己写!在此实现中,Supplier
,Consumer
和Predicate
是返回,接受或测试对象的接口。
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();
}
}
}