Java8中新增了Optional类,Optional类相当于一个容器,这个容器可以包含一个null,也可以包含任何非null的对象。
这个类有两个作用(目的):
Optional
类的Api按照功能,可分为以下几类:
创建Optional实例的api,包括empty()
、of()
、ofNullable()
,返回的是一个Optional
实例
Optaional中的value为null时,做什么的api,包括orElse()
、orElseGet()
、orElseThrow()
,返回值是Optional
中的vlaue
Optaional中的value不为null时,做什么的api,包括ifPresent()
、map()
、flatMap()
,其中ifPresent()
不返回任何值,map()
、flatMap()
返回一个新的Optional
对象
其它分类,get()
、isPresent()
、filter()
getListName()
返回名字列表。如果list
为null
,则创建一个empty list
返回,否则就返回list
。使用了Optioanal
中的orElse()
方法来替代传统的if..else..
,让代码看起来更加简洁。
/**
* 返回名字列表
*
* @return
*/
@Test
public List<String> getListName() {
/*Java8之前的写法*/
/*
List list = null;
if (list == null) {
return Collections.emptyList();
} else {
return list;
}
*/
/*Java8 Optional写法*/
List<String> list = null;
return Optional.of(list).orElse(Collections.emptyList());
}
nameFormatDemo()
名字首字母大写,如果name!=null
则首字母转换为大写,如果name==null
,则赋予no name
值。
/**
* 名字首字母大写
*/
@Test
public void nameFormatDemo() {
final String DEFAULT_NAME = "no name";
/*Java8之前的写法*/
String name = "tom";
if (name != null) {
name = name.substring(0, 1).toUpperCase() + name.substring(1, name.length());
}else{
name = DEFAULT_NAME;
}
System.out.println(String.format("Java8之前的写法,name:%s", name));
/*Java8 Optional写法*/
name = "tom";
//name = null;
Optional<String> nameOptional = Optional.ofNullable(name);
name = nameOptional.map(value -> value.substring(0, 1).toUpperCase() + value.substring(1, value.length())).orElse(DEFAULT_NAME);
System.out.println(String.format("Java8 Optional写法,name:%s", name));
}
printName()
打印名字到控制台。name!=null
则打印name
到控制台,否则什么也不做。ifPresent()
的作用是Optional
中的value
为null时,执行传递函数,否则什么也不做。
/**
* 打印名字到控制台
*/
@Test
public void printName(){
String name = "Tom";
/*Java8之前的写法*/
if (name != null) {
System.out.println(String.format("name:%s",name));
}
/*Java8 Optional写法*/
Optional.ofNullable(name).ifPresent(value -> System.out.println(String.format("name:%s",value)));
}
使用这个类需要注意以下几点:
package com.zhangxy.optional;
import org.junit.jupiter.api.Test;
import org.junit.platform.commons.util.ToStringBuilder;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
/**
* Java8中新增了Optional类
* @author zhangxy
* @credte 2020-06-16 20:46
*/
public class OptionalTest {
@Test
public void emptyDemo() {
Optional<Object> empty = Optional.empty();
System.out.println(empty);//=>Optional.empty
}
/**
* of(T value):用于给Optional实例中的value属性赋值,如果传递的vlaue==null将会抛出NullPointerException
*/
@Test
public void foDemo() {
Optional<String> optional = Optional.of("小明");
System.out.println("optional toString:" + optional);//=>myName is present:Optional[小明]
Optional<String> nullOptional = Optional.of(null);//=>throw java.lang.NullPointerException
}
/**
* ofNullabel(T value):作用同of(T value)相同,不同的是,如果传递的value==null不会抛出任何异常,返回一个empty的Optional实例
*/
@Test
public void ofNullable() {
Optional<String> optional = Optional.ofNullable("小明");
System.out.println("optional toString:" + optional);//=>myName is present:Optional[小明]
Optional<String> nullOptional = Optional.ofNullable(null);
System.out.println("optional toString:" + nullOptional);//=>optional toString:Optional.empty
}
/**
* get():获取Optional实例中的value,如果vlaue==null,会抛出java.util.NoSuchElementException: No value present异常
*/
@Test
public void getDeom() {
Optional<String> optional = Optional.of("小明");
String myName = optional.get();
System.out.println(String.format("myName:%s", myName));//=>myName:小明
optional = Optional.empty();
myName = optional.get();
System.out.println(String.format("myName:%s", myName));//=>java.util.NoSuchElementException: No value present
}
/**
* isPresent():用于判断Optional实例中value值是否为null,true表示不为null,否则为null
*/
@Test
public void isPresentDemo() {
Optional<String> myName = Optional.empty();
System.out.println("myName is present:" + myName.isPresent());//=>false
myName = Optional.of("zhangxy");
System.out.println("myName is present:" + myName.isPresent());//=>true
myName = Optional.ofNullable(null);
System.out.println("myName is present:" + myName.isPresent());//=>false
}
/**
* ifPresent():如果Optional实例的vlaue!=null,则执行Consumer实例的accept(),否则什么也不执行
* 相当于:
* if(value!=null){
* //做一些操作,尤其是这些操作的代码较多时,这样写会显得代码更简洁写
* }else{
* //什么也不做
* }
*/
@Test
public void ifPresentDemo() {
Optional<String> optional = Optional.of("ABC");
optional.ifPresent(value -> System.out.println(String.format("value:%s", value)));//=>value:ABC
optional = Optional.empty();
optional.ifPresent(value -> System.out.println(String.format("value:%s", value)));//什么也不输出
}
/**
* filter(Predicate super T> predicate):根据Predicate实例的test()返回的值为true则返回当前Optional对象,否则返回一个empty的Optional对象
* 相当于,满足过滤条件返回当前Optional对象,否则返回empty的Optional对象
*/
@Test
public void filterDemo() {
Optional<String> optional = Optional.of("ABC").filter(value -> value.contains("A"));
System.out.println(optional);//=>Optional[ABC]
optional = Optional.of("ABC").filter(value -> value.contains("a"));
System.out.println(optional);//=>Optional.empty
}
/**
* map(Function mapper):如果isPresent()==true,则调用Function实例的apply(value)对value进行相关逻辑操作,然后返回一个新的Optional对象,否则返回一个empty的Optional对象
* 相当于:
* if(value!=null){
* //对value进行逻辑操作
* //产生了一个newValue
* //return new Optional,返回一个value类型为NewValue的Optional对象
* }else{
* //return Optional.empty(),返回一个空的Optional对象
* }
*/
@Test
public void mapDemo() {
Optional<UserInfo> userInfoOptional = Optional.of("zhangxy~25").map(value -> {
String[] array = value.split("~");
return new UserInfo(array[0], Integer.parseInt(array[1]));
});
System.out.println(userInfoOptional);
}
/**
* flatMap(Function mapper):和map(Function mapper)作用相同
* 不同的是Function实例的apply()方法如果返回null,将会抛出NullPointerExecption
* 不同的是Function实例的apply()方法如需要显示的返回一个Optional对象
*/
@Test
public void flatMapDemo() {
Optional<UserInfo> userInfoOptional = Optional.of("zhangxy~25").flatMap(value -> {
String[] array = value.split("~");
//return Optional.of(new UserInfo(array[0], Integer.parseInt(array[1])));
return null;
});
System.out.println(userInfoOptional);
}
/**
* orElse(T t):Optional实例的value==null,则返回t(即传入的值),否则返回Optional实例的value
* 相当于:
* if(value==null){
* return t;
* }else{
* reutrn value;
* }
*/
@Test
public void orElseDemo() {
Optional<String> optional = Optional.of("小明");
System.out.println(optional.orElse("小李"));
optional = Optional.empty();
System.out.println(optional.orElse("小李"));
}
/**
* orElseGet(Supplier other):作用和orElse(T t)类似
* Optional实例的value==null,则返回Supplier实例的get()方法返回值,否则返回Optional实例的value
* 相当于:
* if(value==null){
* return get();
* }else{
* reutrn value;
* }
*/
@Test
public void orElseGetDemo() {
Optional<String> optional = Optional.of("小明");
System.out.println(optional.orElse("小李"));
optional = Optional.empty();
System.out.println(optional.orElseGet(() -> {
return "小李";
}));
}
/**
* orElseThrow():作用和orElse(T t)类似
* Optional实例的value==null,则爬出Supplier实例的get()方法返回的异常,否则返回Optional实例的value
* 相当于:
* if(value==null){
* throw get();
* }else{
* return value;
* }
* @throws Exception
*/
@Test
public void orElseThrowDeom() throws Exception {
Optional<String> optional = Optional.of("小明");
optional.orElseThrow(() -> {
return new Exception("测试异常");
});
optional = optional = Optional.empty();
optional.orElseThrow(() -> {
return new Exception("测试异常");
});
}
/**
* 返回名字列表
*
* @return
*/
@Test
public List<String> getListName() {
/*Java8之前的写法*/
/*
List list = null;
if (list == null) {
return Collections.emptyList();
} else {
return list;
}
*/
/*Java8 Optional写法*/
List<String> list = null;
return Optional.of(list).orElse(Collections.emptyList());
}
/**
* 打印名字到控制台
*/
@Test
public void printName(){
String name = "Tom";
/*Java8之前的写法*/
if (name != null) {
System.out.println(String.format("name:%s",name));
}
/*Java8 Optional写法*/
Optional.ofNullable(name).ifPresent(value -> System.out.println(String.format("name:%s",value)));
}
/**
* 名字首字母大写
*/
@Test
public void nameFormatDemo() {
final String DEFAULT_NAME = "no name";
/*Java8之前的写法*/
String name = "tom";
if (name != null) {
name = name.substring(0, 1).toUpperCase() + name.substring(1, name.length());
}else{
name = DEFAULT_NAME;
}
System.out.println(String.format("Java8之前的写法,name:%s", name));
/*Java8 Optional写法*/
name = "tom";
//name = null;
Optional<String> nameOptional = Optional.ofNullable(name);
name = nameOptional.map(value -> value.substring(0, 1).toUpperCase() + value.substring(1, value.length())).orElse(DEFAULT_NAME);
System.out.println(String.format("Java8 Optional写法,name:%s", name));
}
}
class UserInfo implements Serializable {
private String name;
private Integer age;
public UserInfo(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return new ToStringBuilder(this)
.append("name", name)
.append("age", age)
.toString();
}
}
参考资料:https://yanbin.blog/proper-ways-of-using-java8-optional/
https://yanbin.blog/java8-optional-several-common-incorrect-usages/