优雅的判空
对于项目中存在很多需要判空的操作,杂糅在代码里面,增加了很多非业务代码,如何合理的判空,称为了一个很重要的点,直接介绍几种判空操作
1. NullObject模式
- NullObject模式:在获取对象的时候,如果对象为空,就返回一个符合返回类型的空对象。这样在处理的时候都可以按照对象统一处理,只是在空对象中,一些方法的返回是按照不存在的逻辑进行的。
- 在博客的迭代器模式中,使用了空对象模式,可以在迭代的过程中,无须对空对象进行针对性的判断
- 此模式存在继承关系,所以,只能针对对象而言,基础类的话需要进行包装成对象,否则无法使用
- 代码结构图
- 代码
- 空对象的操作接口
//空对象的操作接口,用于处理对象是否为空,在空对象模式中,对象为空会被封装成一个Object, //成为NullObject,在对象中会对原有对象的所有方法实现空实现。以便在处理的时候可以统一处理, //无须判断对象是否为null public interface Nullable { boolean isNull(); }
- 服务的基类,必须实现空对象接口,表示任何一个对象都有可能存在空对象
//业务对象的行为接口 public interface ServiceBase extends Nullable{ //业务对象的方法 void operation(); }
- 实际的业务类
//具体的业务类 public class StudentService implements ServiceBase { @Override public void operation() { System.out.println("student operation....."); } @Override public boolean isNull() { return false; } }
- 空对象类:空对象是ServiceBase的一个空实现,可以在获取Service时,如果没有对应的,可以返回一个空实现,而非判空操作,减少NPE
//空对象,实现空实现 public class NullObject implements ServiceBase { @Override public void operation() { //Do nothing } @Override public boolean isNull() { return true; } }
- 使用工程模式进行获取,业务类
public class ServiceFactory { public static ServiceBase newService(Nullable base){ if(base==null){ return new NullObject(); } return new StudentService(); } }
- 测试类:如果此处没有增加空对象,在运行的时候,需要增加对工程返回的类进行判空操作,如果返回空对象的话,仍然是业务类,只是对象的方法都是空实现
public class MainTest { public static void main(String[] args) { ServiceBase serviceBase = ServiceFactory.newService(null); serviceBase.operation(); } }
2. jdk1.8提供的Optional对象的方法
- 使用Optional方法可以合理的进行判断
- 代码
public class MainTest { public static void main(String[] args) { Object o = Optional.ofNullable(null).orElse(""); System.out.println(o); } }
- 内部实现
- Optional.ofNullable如果传入的对象为null,就返回一个空的Optional对象,它的值时空
public final class Optional<T> { private static final Optional<?> EMPTY = new Optional<>(); private final T value; private Optional() { this.value = null; } public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); } public static<T> Optional<T> empty() { @SuppressWarnings("unchecked") Optional<T> t = (Optional<T>) EMPTY; return t; } }
- 使用orElse对象,判断当前的Optional对象的value是否为null,是的话,返回传入的值,否则返回value
public final class Optional<T> { public T orElse(T other) { return value != null ? value : other; } }
- 缺点:因为是返回的空对象,Optional内部的value值,仍然为null,在获取对象的value值时,仍然需要进行空判断
class Test{ public static void main(String[] args) { ServiceBase serviceBase = getServiceBase(null); serviceBase.operation(); } public static ServiceBase getServiceBase(ServiceBase serviceBase){ //base.get在Optional的value为null的时候报错 Optional<ServiceBase> base = Optional.ofNullable(serviceBase); return base.get(); } }
- 执行结果