文章目录
- 入门`jdk1.8`处理空指针`API`-`Optional`
- 类图结构
- 简要说明
- 常用api
- 实践操作
- 应用场景
- 场景一: 对象不为空,做一些逻辑处理
- 场景二:对象为空抛异常,或者对象某个字段为空抛指定异常
- 场景三:级联判空,父节点,子节点,子子属性
- 场景四:属性为空,默认值赋值
入门jdk1.8
处理空指针API
-Optional
类图结构
简要说明
/**
* A container object which may or may not contain a non-null value.
* If a value is present, {@code isPresent()} will return {@code true} and
* {@code get()} will return the value.
*
* <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(java.lang.Object) orElse()}
* (return a default value if value not present) and
* {@link #ifPresent(java.util.function.Consumer) ifPresent()} (execute a block
* of code if the value is present).
*
* <p>This is a <a href="../lang/doc-files/ValueBased.html">value-based</a>
* class; use of identity-sensitive operations (including reference equality
* ({@code ==}), identity hash code, or synchronization) on instances of
* {@code Optional} may have unpredictable results and should be avoided.
*
* @since 1.8
*/
一个可以包含非空值也可以不包含非空值的容器对象。如果一个值存在,isPresent()将返回true和get()将返回值。
构造方法
/**
* 空的Optional
*/
private static final Optional<?> EMPTY = new Optional<>();
/**
* If non-null, the value; if null, indicates no value is present
*/
private final T value;
/**
* Constructs an empty instance.
*
* @implNote Generally only one empty instance, {@link Optional#EMPTY},
* should exist per VM.
*/
private Optional() {
this.value = null;
}
常用api
构建空的Optional实例对象
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
构建指定类型的Optional
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
构建非空的对象
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
构建各种对象,对空对象做了处理
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
获取对应数值对象情况
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
如果具体数值存在,返回true,否则false
/**
* Return {@code true} if there is a value present, otherwise {@code false}.
*
* @return {@code true} if there is a value present, otherwise {@code false}
*/
public boolean isPresent() {
return value != null;
}
如果Optional存在实例对象,进行逻辑操作,通过Consumer处理
/**
* If a value is present, invoke the specified consumer with the value,
* otherwise do nothing.
*
* @param consumer block to be executed if a value is present
* @throws NullPointerException if value is present and {@code consumer} is
* null
*/
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
过滤操作,筛选数据,前提是不能为空
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
实践操作
// 创建空的Optional,内部通过构造方法new一个Optional
Optional<Object> empty = Optional.empty();
// 根据非空对象创建Optional,如果对象为空,抛异常空指针
User user = User.builder().userName("小米粒").age(10).build();
Optional<User> userOptional = Optional.of(user);
log.info("userOptional : [{}]" , userOptional);
// userOptional : [Optional[NoDaoTest.User(userName=小米粒, age=10, loginTime=null, account=null)]]
// 可以接收对象为空
User nullUser=null;
Optional<User> nullUserOptional = Optional.ofNullable(nullUser);
log.info("nullUserOptional : [{}]" , nullUserOptional);
// nullUserOptional : [Optional.empty]
// 判断Optional是否包含对象
boolean userOptionalPresent = nullUserOptional.isPresent();
log.info("userOptionalPresent : [{}]" , userOptionalPresent);
// userOptionalPresent : [false]
boolean userOptionalPresent1 = userOptional.isPresent();
log.info("userOptionalPresent1 : [{}]" , userOptionalPresent1);
// userOptionalPresent1 : [true]
// 如果Optional包含属性value-》业务数据,可以做一些特殊处理
userOptional.ifPresent(item->item.setAge(88));
log.info("如果Optional包含属性value-》业务数据,可以做一些特殊处理 userOptional : [{}]" , userOptional);
// 如果Optional包含属性value-》业务数据,可以做一些特殊处理 userOptional : [Optional[NoDaoTest.User(userName=小米粒, age=88, loginTime=null, account=null)]]
// 获取容器中属性,类似于getter方法
User userTarget = userOptional.get();
log.info("userTarget : [{}]" , userTarget);
// userTarget : [NoDaoTest.User(userName=小米粒, age=88, loginTime=null, account=null)]
// 如果Optional中属性为空,可以创建新的对象返回,不为空正常返回
User userOrElse = nullUserOptional.orElse(User.builder().userName("笑一笑").build());
log.info("userOrElse : [{}]" , userOrElse);
// userOrElse : [NoDaoTest.User(userName=笑一笑, age=null, loginTime=null, account=null)]
// 如果Optional属性为空,通过Supplier函数创建对象返回,否则返回原始对象
User userOrElseGet = nullUserOptional.orElseGet(() -> User.builder().userName("唠一唠").build());
log.info("userOrElseGet : [{}]" , userOrElseGet);
// userOrElseGet : [NoDaoTest.User(userName=唠一唠, age=null, loginTime=null, account=null)]
// 如果Optional属性为空,抛出指定异常
// User userOrElseThrow = nullUserOptional.orElseThrow(() -> new IllegalArgumentException("指定异常抛出信息"));
// log.info("userOrElseThrow : [{}]" , userOrElseThrow);
// 过滤操作
User userFilter = User.builder().userName("过滤名称").build();
Optional.ofNullable(userFilter)
.filter(item->StringUtils.equals("过滤名称", item.getUserName()))
.ifPresent(x->log.info("x : [{}]" , x)
);
// x : [NoDaoTest.User(userName=过滤名称, age=null, loginTime=null, account=null)]
User userMap = User.builder().userName("map").build();
Optional.ofNullable(userMap)
.map(item->{
item.setAge(10);
return item;
});
log.info("userMap : [{}]" , userMap);
// userMap : [NoDaoTest.User(userName=map, age=10, loginTime=null, account=null)]
应用场景
场景一: 对象不为空,做一些逻辑处理
// 以前开发
if(userInfo != null){
userInfo.setProperty("*");
}
// 现在开发
Optional.ofNullable(userMap)
.ifPresent(item->item.setAge(99));
log.info("场景一:userMap [{}]" , userMap);
// 场景一:userMap [NoDaoTest.User(userName=map, age=99, loginTime=null, account=null)]
场景二:对象为空抛异常,或者对象某个字段为空抛指定异常
// 以前开发
if(userInfo != null){
if(userInfo.getUserName() != null && userInfo.getUserName() != ""){
// 逻辑处理
}
}
// 现在开发
// 无论是user为空还是名字为空,抛异常
User userEmpty = User.builder().build();
User nullUser = null;
Optional.ofNullable(userEmpty)
.filter(item -> StringUtils.isNotBlank(item.getUserName()))
.orElseThrow(() -> new IllegalArgumentException("对象为空或者姓名为空"))
;
场景三:级联判空,父节点,子节点,子子属性
Student son = Student.builder().build();
User parentUser = User.builder()
.userName("父节点名称")
.student(son)
.build();
Optional.ofNullable(parentUser)
.map(User::getStudent)
.map(Student::getStuName)
.orElseThrow(()->new IllegalArgumentException("子节点不为空或者子节点用户信息不为空"));
Optional.ofNullable(parentUser)
.map(User::getStudent)
.map(Student::getStuName)
.orElseThrow(()->new IllegalArgumentException("子节点不为空或者子节点用户信息不为空"));
场景四:属性为空,默认值赋值
Optional.ofNullable(userMap)
.filter(item -> StringUtils.isBlank(item.getUserName()))
.map(item -> {
item.setUserName("李华");
return item;
});
// 16:19:21.164 [main] INFO com.geekmice.springbootselfexercise.NoDaoTest - userMap : [NoDaoTest.User(userName=李华, age=99, loginTime=null, account=null, student=null)]