jdk8新特性-Optional

摘要

Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException)。它提供了可设置为空值(ofNullable)、值是否存在(isPresent)、值为空时取默认值(orElse)等方法,让我们在操作对象时可以优雅处理空值。


示例

1.empty()

通过empty创建一个空的Optional,此时get时会报错

2.get()

get()方法获取Optional值,如果为空时会报java.util.NoSuchElementException: No value present

System.out.println("-----Optional.empty-----");
Optional<String> optional=Optional.empty();
optional.get();

输出

-----Optional.empty-----
java.util.NoSuchElementException: No value present

3.of()

of()向Optional填充值,此时不能为空,为空时报错

System.out.println("-----Optional.off-----");
User emptyUser=null;
Optional<User> optional = Optional.of(emptyUser);

输出

-----Optional.off-----
java.lang.NullPointerException

4.ofNullable()

ofNullable()向Optional填充值,此时可为空

System.out.println("-----Optional.ofNullable-----");
User emptyUser=null;
Optional.ofNullable(emptyUser);

5.isPresent()

判断Optional值是否存在

System.out.println("-----Optional.isPresent-----");
Optional<String> optional= Optional.empty();
 System.out.println(optional.isPresent());

输出

-----Optional.isPresent-----
false

该方法除了执行检查,还接受一个Consumer(消费者) 参数,如果对象不是空的,就对执行传入的 Lambda 表达式:

System.out.println("-----Optional.isPresentLambda-----");
User user=new User(1,"小杨");
Optional<User> optional= Optional.of(user);
optional.ifPresent( u -> System.out.println("用户名:"+u.getName()));

输出

-----Optional.isPresentLambda-----
用户名:小杨

6.orElse()

orElse()如果有值则返回该值,否则返回传递给它的参数值

System.out.println("-----Optional.orElse-----");
User emptyUser=null;
User user=new User(1,"小杨");
User res= Optional.ofNullable(emptyUser).orElse(user);
System.out.println(toString(res));

输出

-----Optional.orElse-----
{“id”:1,“name”:“小杨”}

7.orElseGet()

有值的时候返回值,如果没有值,它会执行作为参数传入的 Supplier(供应者) 函数式接口,并将返回其执行结果。

@Test
public void orElseGet(){
    System.out.println("-----Optional.orElseGet-----");
    User emptyUser=null;
    User res= Optional.ofNullable(emptyUser).orElseGet(()->getDefaultUser());
    System.out.println(toString(res));
}
private User getDefaultUser(){
    System.out.println("创建默认用户");
    User user=new User(0,"管理员");
    return user;
}

输出

-----Optional.orElseGet-----
创建默认用户
{“id”:0,“name”:“管理员”}

orElse()与orElseGet()在值为空时没有区别,但是在有值时orElse仍然会运行创建orElse()中的对象

@Test
public void orElseGetAndOrElse(){
    System.out.println("-----Optional.orElseGetAndOrElse-----");
    User defUser=new User(1,"小杨");
    System.out.println("Optional.orElse");
    User user = Optional.ofNullable(defUser).orElse(getDefaultUser());
    System.out.println(toString(user));
    System.out.println("Optional.orElseGet");
    User res= Optional.ofNullable(defUser).orElseGet(()->getDefaultUser());
    System.out.println(toString(res));
}

private User getDefaultUser(){
    System.out.println("创建默认用户");
    User user=new User(0,"管理员");
    return user;
}

输出

-----Optional.orElseGetAndOrElse-----
Optional.orElse
创建默认用户
{“id”:1,“name”:“小杨”}
Optional.orElseGet
{“id”:1,“name”:“小杨”}

8.orElseThrow()

对象为空的时候抛出异常

System.out.println("-----Optional.orElseThrow-----");
String res = (String)Optional.empty().orElseThrow( () -> new IllegalArgumentException("值为空"));

输出

-----Optional.orElseThrow-----
java.lang.IllegalArgumentException: 值为空

9.map()

对值调用作为参数的函数,然后将返回的值包装在 Optional 中。

System.out.println("-----Optional.map-----");
User user=new User(1,"小杨");
String userName=Optional.ofNullable(user).map(u->u.getName()).get();
System.out.println(userName);

输出

-----Optional.map-----
小杨

10.filter()

返回过滤结果为 true 的值。如果测试结果为 false,会返回一个空的 Optional

System.out.println("-----Optional.filter-----");
System.out.println("-----name=小杨-----");
User user=new User(1,"小杨");
String res=Optional.ofNullable(user).filter(u->u.getName().equals("小杨")).map(u->u.getName()).orElse("用户不存在");
System.out.println(toString(res));
System.out.println("-----name=小张-----");
String res1=Optional.ofNullable(user).filter(u->u.getName().equals("小张")).map(u->u.getName()).orElse("用户不存在");
System.out.println(toString(res1));

输出

-----Optional.filter-----
-----name=小杨-----
“小杨”
-----name=小张-----
“用户不存在”


优雅处理NPE

1.传统NPE处理

private static String defaultPreUrl="http://127.0.0.1/preview/miss.jpg";
private static FileV1 file1=new FileV1(1,"测试文件",null,"http://127.0.0.1/file/test.pdf");
private static ResourceV1 resource1 = new ResourceV1(1,"测试资源",file1);
@Test
public void NPEV1(){
   System.out.println("-----------传统NPE判断-----------");
   String url=defaultPreUrl;
   if (file1 != null) {
       FileV1 file = resource1.getFile();
       if (file != null) {
           PreviewV1 preview = file.getPreview();
           if (preview != null) {
               url = preview.getUrl();
           }
       }
   }
   System.out.println(url);
}
class ResourceV1{
    private Integer id;
    private String name;
    private FileV1 file;
    public ResourceV1(Integer id, String name, FileV1 file) {
        this.id = id;
        this.name = name;
        this.file = file;
    }
	//get set
}

class FileV1{
    private Integer id;
    private String name;
    private PreviewV1 preview;
    private String url;
    public FileV1(Integer id, String name, PreviewV1 preview, String url) {
        this.id = id;
        this.name = name;
        this.preview = preview;
        this.url = url;
    }
	//get set
}

class PreviewV1{
    private Integer id;
    private String name;
    private String url;
    public PreviewV1(Integer id, String name, String url) {
        this.id = id;
        this.name = name;
        this.url = url;
    }
	//get set
}

输出

-----------传统NPE判断-----------
http://127.0.0.1/preview/miss.jpg

2.通过Optional处理NPE

private static String defaultPreUrl="http://127.0.0.1/preview/miss.jpg";
private static FileV2 file2=new FileV2(1,"测试文件",null,"http://127.0.0.1/file/test.pdf");
private static ResourceV2 resource2 = new ResourceV2(1,"测试资源",file2);
@Test
public void NPEV2(){
   System.out.println("-----------Optional NPE判断-----------");
   String result = Optional.ofNullable(resource2)
           .flatMap(ResourceV2::getFile)
           .flatMap(FileV2::getPreview)
           .map(PreviewV2::getUrl)
           .orElse(Optional.of(defaultPreUrl)).get();
   System.out.println(result);
}
class ResourceV2{
    private Integer id;
    private String name;
    private FileV2 file;
    public ResourceV2(Integer id, String name, FileV2 file) {
        this.id = id;
        this.name = name;
        this.file = file;
    }
    public Optional<FileV2> getFile() {
        return Optional.ofNullable(file);
    }
    public void setFile(FileV2 file) {
        this.file = file;
    }
    //get set
}

class FileV2{
    private Integer id;
    private String name;
    private PreviewV2 preview;
    private String url;
    public FileV2(Integer id, String name, PreviewV2 previewV2, String url) {
        this.id = id;
        this.name = name;
        this.preview = preview;
        this.url = url;
    }
    public Optional<PreviewV2> getPreview() {
        return Optional.ofNullable(preview);
    }
    public void setPreview(PreviewV2 preview) {
        this.preview = preview;
    }
	//get set
}

class PreviewV2{
    private Integer id;
    private String name;
    private String url;
    public PreviewV2(Integer id, String name, String url) {
        this.id = id;
        this.name = name;
        this.url = url;
    }
    public Optional<String> getUrl() {
        return Optional.ofNullable(url);
    }
    public void setUrl(String url) {
        this.url = url;
    }
    //get set
}

输出

-----------Optional NPE判断-----------
http://127.0.0.1/preview/miss.jpg

发布了43 篇原创文章 · 获赞 28 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/u014395955/article/details/104040512