码农在囧途
随着时间的推移,曾经我们觉得重要的东西,可能在今天看来是如此的浅薄和无知,同理,今天我们放不下,想不开,觉得重要的东西,多年后我们可能也会觉得也就那样,所以,今天的的所有烦恼,忧愁,想不开,其实我们都没必要过于在意,因为有些东西随着时间的冲刷,也就那样了。
前言
Java8提供了Optional接口,Optional接口能够是我们的代码变得更加的优雅,可读性更高,同时能够很好的避免空指针,因为空指针是一个很让人头疼的问题,特别对于调用第三方接口,如果不知道对象的规约的时候,我们在取值的时候无法直到那些值能为空,那些不能为空,所以容易出现空指针,如果我们谨慎一点,可能会对每一个值进行判空处理,但是将会充斥着大量的if语句,甚是不雅观。
下面我们介绍一下Optional类的方法
empty()
返回一个空的Optional对象 Optional.empty
of(T value)
参数传入一个对象,返回一个Option对象,value不能为空,如果为null,将抛出空指针异常
/** * @author 刘牌 * @date 2022-03-2921:52 */ public class OptionalTest { public static void main(String[] args) { User user = null; Optional<User> optional = Optional.of(user); System.out.println(user); } }
ofNullable(T value)
参数传入一个对象,可以为空,如果为空,将返回一个空的Optional对象,就等于Optional.empty(),输出的值为Optional.empty
,如果不为空,返回一个不为空的Optional对象
/** * @author 刘牌 * @date 2022-03-2921:52 */ public class OptionalTest { public static void main(String[] args) { User user = null; Optional<User> optional = Optional.ofNullable(user); System.out.println(optional); } }
get()
获取Optional中的值,这个值也就是我们的值,Optional相当于就是一个外壳。
public class OptionalTest { public static void main(String[] args) { User user = null; Optional<User> optional = Optional.ofNullable(user); User user1 = optional.get(); } }
isPresent()
判断Optional对象中是否有值,如果有值,返回true,没值返回false。
true
public class OptionalTest { public static void main(String[] args) { User user = new User(); Optional<User> optional = Optional.ofNullable(user); System.out.println(optional.isPresent()); } }
false
public class OptionalTest { public static void main(String[] args) { User user = null; Optional<User> optional = Optional.ofNullable(user); System.out.println(optional.isPresent()); } }
ifPresent(Consumer<? super T> consumer)
ifPresent参数是一个函数式接口,无返回值,会将Optional中的值作为参数传递到ifPresent()中
public class OptionalTest { public static void main(String[] args) { User user = new User(); Optional<User> optional = Optional.ofNullable(user); optional.ifPresent(s -> System.out.println(s)); } }
filter(Predicate<? super T> predicate)
是一个Predicate函数接口,会将Optional中的值作为参数传入,如果符合规则,那么返回一个Optional对象,否则返回一个空的Optional 对象(Optional.empty) 符合规则,返回Optional对象
public class OptionalTest { public static void main(String[] args) { User user = new User(); user.setUsername("我是小四哥"); Optional<User> optional = Optional.ofNullable(user); Optional<User> optional1 = optional.filter(v -> v.getUsername().equals("我是小四哥")); System.out.println(optional1); } }
不符合规则,返回空Optional(Optional.empty
)
public class OptionalTest { public static void main(String[] args) { User user = new User(); user.setUsername("我是小四哥"); Optional<User> optional = Optional.ofNullable(user); Optional<User> optional1 = optional.filter(v -> v.getUsername().equals("我不是小四哥")); System.out.println(optional1); } }
map(Function<? super T, ? extends U> mapper)
参数是一个Function函数式接口,会将Optional中的值作为参数传递到map中,如果传入的值为空,则返回一空的Optional对象,相当于Optional.empty(), 如果不为空,我们可以返回一个可以描述描述结果的返回值(Optional中的值,这个值可以重新赋值),如下面的返回一个tempUser
Optional中的值为空
public class OptionalTest { public static void main(String[] args) { User user = null; Optional<String> optional = Optional.ofNullable(user).map(OptionalTest::getMap); System.out.println(optional); //Optional.empty } public static String getMap(User user){ return user.getUsername(); } }
Optional中的值不为空
public class OptionalTest { public static void main(String[] args) { User user = new User(); user.setUsername("我是小四哥"); user.setAge(20); Optional<String> optional = Optional.ofNullable(user).map(OptionalTest::getMap); System.out.println(optional); // Optional[我是小四哥] } public static String getMap(User user){ return user.getUsername(); } }
flatMap(Function<? super T, Optional> mapper)
如果Optional中值存在,那么返回一个基于Optional的值(如Optional),如果Optional中的值不存在,则返回一空的Optional对象,相当于Optional.empty(),与map不同, map返回的是一个值,而flatMap返回一个基于Optional的值
public class OptionalTest { public static void main(String[] args) { User user = new User(); user.setUsername("我是小四哥"); user.setAge(20); Optional<String> optional = Optional.ofNullable(user).flatMap(OptionalTest::getFlatMap); System.out.println(optional); } public static Optional<String> getFlatMap(User user){ return Optional.ofNullable(user).map(User::getUsername); } }
orElse(T other)
如果Optional中的值不为空,则返回Optional中的值,如果为空,则返回other值,
String value = "2"; String orElse = Optional.ofNullable(value).orElse("1"); System.out.println(orElse); //2 String value = null; String orElse = Optional.ofNullable(value).orElse("1"); System.out.println(orElse); //1
orElseGet(Supplier<? extends T> other)
如果Optional中存在值,则返回值,否则返回other调用的结果
Optional中存在值
public class OptionalTest { public static void main(String[] args) { String value = null; String orElse = Optional.ofNullable(value).orElseGet(OptionalTest::get); System.out.println(orElse); // 123 } public static String get(){ return "123"; } }
Optional中不存在值
public class OptionalTest { public static void main(String[] args) { String value = "2"; String orElse = Optional.ofNullable(value).orElseGet(OptionalTest::get); System.out.println(orElse); // 2 } public static String get(){ return "123"; } }
orElseThrow(Supplier<? extends X> exceptionSupplier)
如果Optional中的值存在,则返回值,值不存在,则抛出异常函数Supplier中的异常
public class OptionalTest { public static void main(String[] args) { String value = null; String orElse = Optional.ofNullable(value).orElseThrow(() -> new RuntimeException("不存在值")); System.out.println(orElse); } }
输出
Exception in thread "main" java.lang.RuntimeException: 不存在值 at com.steak.javase.optional.OptionalTest.lambda$main$0(OptionalTest.java:14) at java.util.Optional.orElseThrow(Optional.java:290) at com.steak.javase.optional.OptionalTest.main(OptionalTest.java:13)
实战,去除if判断
我们将一个从远程接口获取了一个用户的信息,包含家庭信息,学历信息,个人信息,然后封装成一个VO,再返回前端进行展示。
家庭实体Family
/** * @author 刘牌 * @date 2022-03-3023:22 */ @Data @Accessors(chain = true) public class Family { private String fatherName; private String motherName; }
学历实体Education
@Data @Accessors(chain = true) public class Education { private String education; private String schoolName; private Date admissionTime; private Date graduationTime; }
用户信息实体UserInfo
/** * @author 刘牌 * @date 2022-03-3023:16 */ @Data @Accessors(chain = true) public class UserInfo { private String name; private Integer age; private Family family; private Education education; }
用户VO,返回前端的视图对象
/** * @author 刘牌 * @date 2022-03-2922:02 */ @Data @Accessors(chain = true) public class UserVO { private String username; private Integer userAge; private String edu; private String school; private Date admissionDate; private Date graduationDate; private String mother; private String father; }
如果没有做判空处理,如下代码,因为getUser()接口中并没有为family属性设值,所以为null,那么main方法中对其进行赋值的时候,肯定会抛出空指针异常NullPointerException。
/** * @author 刘牌 * @date 2022-03-2921:52 */ public class OptionalTest { public static void main(String[] args) { UserInfo userInfo = getUser(); UserVO user = new UserVO(); user.setUsername(userInfo.getName()).setUserAge(userInfo.getAge()) .setEdu(userInfo.getEducation().getEducation()) .setSchool(userInfo.getEducation().getSchoolName()) .setAdmissionDate(userInfo.getEducation().getAdmissionTime()) .setGraduationDate(userInfo.getEducation().getGraduationTime()) .setFather(userInfo.getFamily().getFatherName()) .setMother(userInfo.getFamily().getMotherName()); System.out.println(user); } public static UserInfo getUser(){ Family family = new Family().setFatherName("father") .setMotherName("mother"); Education education = new Education().setEducation("本科") .setSchoolName("家里蹲大学") .setAdmissionTime(new Date()) .setGraduationTime(new Date()); return new UserInfo() .setName("小四哥") .setAge(24) .setEducation(education); } }
所以我们需要做判空校验,那么大多数人肯定会使用如下方式进行判断,先判断userInfo是否null,再接着判断education属性和family属性是否为null,为null不赋值,这样就能避免空指针,这是绝大多数人都会这样做的,这样做确实是没错的,但是我们发现代码中存在很多if判空操作,看起来其实不怎么好看。
if (null != userInfo){ user.setUsername(userInfo.getName()).setUserAge(userInfo.getAge()); if (null != userInfo.getEducation()){ user.setEdu(userInfo.getEducation().getEducation()) .setSchool(userInfo.getEducation().getSchoolName()) .setAdmissionDate(userInfo.getEducation().getAdmissionTime()) .setGraduationDate(userInfo.getEducation().getGraduationTime()); } if (null != userInfo.getFamily()){ user.setFather(userInfo.getFamily().getFatherName()) .setMother(userInfo.getFamily().getMotherName()); } }
使用Optional接口进行改造,额~~~,这好像也没改造出啥东西来啊,没错,确实没改造出什么新花样来,除了增加一些函数操作,基本没啥改变,但是我们能直观的看出,代码比上面的会好维护一点,因为大家都比较烦if,那么,除了好看一点,好维护一点,还有啥好处呢,我觉得如果你对一些返回的结果不能很确定其返回值值的情况下,那么使用Optional来避免空指针是一个很好的办法,因为在开发中可能并不会想得那么周到,可能某处因为疏忽或者没考虑到,忘记加了if判空,那么后续可能会导致空指针,如果使用Optional的话,那么这个问题能够得到避免。
Optional.ofNullable(userInfo).ifPresent(userInfoI -> { user.setUsername(userInfoI.getName()).setUserAge(userInfoI.getAge()); Optional.ofNullable(userInfoI.getFamily()).ifPresent(family -> { user.setFather(userInfo.getFamily().getFatherName()).setMother(userInfo.getFamily().getMotherName()); }); Optional.ofNullable(userInfoI.getEducation()).ifPresent(education -> { user.setEdu(userInfo.getEducation().getEducation()) .setSchool(userInfo.getEducation().getSchoolName()) .setAdmissionDate(userInfo.getEducation().getAdmissionTime()) .setGraduationDate(userInfo.getEducation().getGraduationTime()); }); });
获取用户毕业时间,去除if多重判断
不使用Optional,使用if判断
public static Date getGraduationTime(UserInfo userInfo){ if (null != userInfo){ if (null != userInfo.getEducation()){ return userInfo.getEducation().getGraduationTime(); } } return null; }
使用Optional
public static Date getGraduationTime(UserInfo userInfo){ return Optional.ofNullable(userInfo) .map(UserInfo::getEducation) .map(Education::getGraduationTime) .orElse(null); }
关于Optional,里面还有很多好用的方法和操作,我们就不展开了。
今天的分享就到这里,感谢你的观看,我们下期见!