欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

optional用法

程序员文章站 2022-01-05 10:50:31
...

java8的改进中一个非常有用的就是optional,一句话概括,optional允许使用一个不确定是否为null的对象并且在对象为null的时候采取一系列的应对措施而不必抛出nullpointerException。

这项改进对于经常面对空指针异常的程序是个福音,因为按照以往的方式,要避免空指针异常,就必需进行null判断,如if(obj==null),另一种方式就是抛出异常并处理,然而这两种方式的语言表达能力并不好,复杂的场合可读性太差,所以使用optional可以解决这个问题。

public class Gen {
	//创封装一个为空的Optional<User>对象
	public Optional<User> user = Optional.empty();
	//封装一个Optional<User>,如果提供的User为null,则返回一个空的Optional<User>
        public Optional<User> user = Optional.ofNullable(new User());
	public void exe() {
		//get从Optional<User>去除user对象,如果对象为空,则抛出NoSuchElementEception
		user.get();
		
		//get相当于不判断user是否为null直接调用,为null则照旧抛出nullpointerException
		user.get().setId(10);
		user.get().setEmail("123");
		
		//of将一个对象封装为optional对象,如果对象为null,抛出NoSuchElementEception
		Optional.of(new User());
		
		//isPresent相当于if(user==null)
		System.out.println(user.isPresent());
		
		//ifPresent相当于if(user!=null)
		//			System.out.println(user.getId());
		//		else
		//			doNothing
		user.ifPresent((user)->System.out.println(user.getId()));
		
		//map和上面类似,但是必须使用对象本身的函数
		System.out.println(user.map((user)->user.getId()));
		
		//orElse通常跟map搭配,不通过则返回默认值
		System.out.println(user.map((user)->user.getId()).orElse(100));
		
		//orElseGet跟orElse类似,不通过返回一个Supplier<T>签名的函数
		Supplier<Integer> s= ()->new Integer(12);
		user.map((user)->user.getId()).orElseGet(s);
		
		//orElseThrow则是返回一个Supplier<Throwable>签名的函数
		Supplier<NumberFormatException> n = ()->new NumberFormatException();
		user.map((user)->user.getId()).orElseThrow(n);		
		
	}
	
	public static void main(String[] args) throws Exception {
		new Gen().exe();
	}
	
}

我们增加一个方法,用于返回Gen中的一个Optional对象

public Optional<User> getUser() {
		return user;
	}

如果我们希望输出一个Gen对象中的User对象的email,第一时间想到的是如下做法:

Optional<Gen> gen = Optional.ofNullable(new Gen());
		String email = gen.map(Gen::getUser).map(User::getEmail).orElse("noemail");//类型检查不通过
		System.out.println(email);

但是出现了类型错误,因为map方法跟stream类似,返回的是一个流,只不过是只有一个对象的流,并且这个流是嵌套的,也就是说第一个map返回的是一个Optional<Optional<User>>的对象流,对他进行getEmail操作显然是不支持的,这个时候使用flapmap:

String email = gen.flatMap(Gen::getUser).map(User::getEmail).orElse("noemail");

flatmap跟stream的类似,将嵌套的流扁平化为单一的流,从而解这种引用链。

比flatmap更进一步处理的有filter,例:

{
		user.get().setEmail("hello");//初始化一下属性
	}
gen.flatMap(Gen::getUser).filter((u)->u.getEmail().equals("hello"));

那么当user不为null且email为hello是,返回其optional对象,否则返回空的optional对象。

另外,optional对象作为属性,该属性是不能被序列化的,它没有实现序列化接口。



相关标签: optional