基本要义
阿里巴巴Java开发手册关于异常处理的规范:
【推荐】防止 NPE,是程序员的基本修养,注意 NPE 产生的场景:
1)返回类型为基本数据类型,return 包装数据类型的对象时,自动拆箱有可能产生 NPE。
反例:public int f() { return Integer 对象}, 如果为 null,自动解箱抛 NPE。 参考Java条件运算符的陷阱:自动拆箱与NPE - 知乎 (zhihu.com)
2) 数据库的查询结果可能为 null。
3) 集合里的元素即使 isNotEmpty,取出的数据元素也可能为 null。
4) 远程调用返回对象时,一律要求进行空指针判断,防止 NPE。
场景:@Resource注入各种涉及到hsf远程调用的helper类时,需要对结果进行空指针判断。
5) 对于 Session 中获取的数据,建议 NPE 检查,避免空指针。
6) 级联调用 obj.getA().getB().getC();一连串调用,易产生 NPE。
正例:使用 JDK8 的 Optional 类来防止 NPE 问题。
基本使用
import org.junit.Test;
import java.util.Optional;
/**
* @Author jiangxuzhao
* @Description
* @Date 2023/6/5
*/
public class OptionalTest {
/**
* 问题引入1
*/
@Test
public void problem1(){
String name=null;
System.out.println(name.length()); // NPE
}
/**
* 问题引入2
*/
@Test
public void problem2(){
System.out.println(problem2_1()); // 自动拆箱NPE
}
public int problem2_1(){
Integer a=null;
return a; // 会调用a.intValue()
}
/**
* 以前需要进行非空判断
*/
@Test
public void test1(){
String name=null;
if(name!=null){
System.out.println("字符串长度为:"+name.length());
} else{
System.out.println("字符串长度为空");
}
}
// Optional是一个可以为null的容器对象,它的作用就是避免Null检查,防止NullPointerException
/**
* Optional创建方式
*/
@Test
public void test2(){
// 第一种方式 of方法,of不支持null
Optional<String> op1 = Optional.of("zhangsan");
// Optional<Object> op2 = Optional.of(null);
// 第二种方式 ofNullable方法,支持null
Optional<String> op3 = Optional.ofNullable("zhangsan");
Optional<Object> op4 = Optional.ofNullable(null);
// 第三种方式 通过Empty()直接创建一个空对象null
Optional<String> op5 = Optional.empty();
}
/**
* Optional常见方法
* get():如果Optional有值则返回,否则抛出NoSuchElementException异常
* isPresent(): 判断Optional是否有value,有则返回true,否则返回false
* T orElse(T t):如果Optional<T>包含value,则返回该value,否则返回t,其中value需要为类型T,也可以为null
* orElseGet(Supplier<? extends T> other): 如果Optional包含值,则返回该value,否则返回Supplier<? extends T> other的返回值,其中supplier输入void返回<T>
*/
@Test
public void test3(){
Optional<String> op1 = Optional.of("zhangsan");
Optional<String> op2 = Optional.empty();
// String s1 = op1.get();
// System.out.println("用户名称为:"+s1);
// System.out.println(op2.get()); // 空对象
if(op1.isPresent()){
System.out.println("用户名称为:"+op1.get()); // 用户名称为:zhangsan
}else{
System.out.println("s1是一个空对象");
}
if(op2.isPresent()){
System.out.println("用户名称为:"+op2.get());
}else{
System.out.println("s2是一个空对象"); // s2是一个空对象
}
String s3 = op1.orElse(null);
System.out.println(s3); // zhangsan
String s4 = op2.orElse("王五");
System.out.println(s4); // 王五
String s5 = op2.orElseGet(()->{return "666";});
System.out.println(s5); // 666
}
/**
* ifPresent(Consumer<? super T> consumer): 如果存在值就做Consumer<? super T> consumer的动作,其中consumer输入<T>返回void
*/
@Test
public void test4(){
Optional<String> op1 = Optional.of("zhangsan");
Optional<String> op2 = Optional.empty();
op1.ifPresent(s-> System.out.println("有值:"+s)); //有值:zhangsan
op1.ifPresent(System.out::println); //zhangsan
}
/** 将偶数值进行过滤
* op.filter(Predicate<? super T> predicate):对Optional<T>操作,根据predicate条件输出Optional<U>,其中Predicate<? super T> predicate输入<T>,输出boolean
*
* public Optional<T> filter(Predicate<? super T> predicate) {
* Objects.requireNonNull(predicate);
* if (!isPresent())
* return this;
* else
* return predicate.test(value) ? this : empty();
* }
*/
@Test
public void test5(){
Optional<Integer> op = Optional.ofNullable(2222);
Optional<Integer> ans=op.filter(s->s%2==0);
System.out.println(ans); // 是偶数,过滤成功,输出Optional[2222]
Optional<Integer> op2 = Optional.ofNullable(2223);
Optional<Integer> ans2=op2.filter(s->s%2==0);
System.out.println(ans2); // 是奇数,过滤失败,输出Optional.empty
}
/**
* 将Person对象的name改为大写并打印出名字,通过Optional方式实现
* op.map(Function<? super T, ? extends U> mapper):对Optional<T>操作,输出Optional<U> ,其中Function<? super T, ? extends U> mapper输入<T>,输出<U>
*
* map判断了value是否为null,如果为null返回empty(),否则返回mapper处理完后的Optional<U>
* public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
* Objects.requireNonNull(mapper);
* if (!isPresent())
* return empty();
* else {
* return Optional.ofNullable(mapper.apply(value));
* }
* }
*/
@Test
public void test6(){
Person person = new Person("zhangsan");
Optional<Person> op = Optional.ofNullable(person);
String name=getNameOptional(op);
System.out.println(name); // ZHANGSAN
System.out.println(person.getName()); // zhangsan,注意并未修改原来Person的属性,getNameOptional中是对新生成的Optional<String>的操作
Person person2 = new Person(null);
Optional<Person> op2 = Optional.ofNullable(person2);
String name2 = getNameOptional(op2);
System.out.println(name2); //空值
}
public String getNameOptional(Optional<Person> op){
String msg=op.map(p->p.getName()) // Optional<String>或者Empty()
.map(p->p.toUpperCase()) // Optional<String>或者Empty()
.orElse("空值");
return msg;
}
class Person{
private String name;
public Person(String name){
this.name=name;
}
public String getName(){
return this.name;
}
}
}