做Java开发的朋友,想必编程时经常遇到NullPointerException。Java 8推出了一个Optional的工具类,用好它可以避免因为空指针null导致的这个异常。
咱们就用这篇文章,学习一下Java 8新推出的Optional和Lambda Expression。
通过下面四个简单的例子来学习一下吧。例1
我有这样一个简单的Person类:
class Person {
private String mName;
public Person(String name) {
mName = name;
}
public void greet() {
System.out.println("I am: " + mName);
}
}
下列代码第21行会执行出错,进入第23行的异常处理:
public void scenario1() {
Person person = null;
try {
Optional
p1 = Optional.of(person);
}
catch ( Exception e) {
System.out.println("Error: " + e.getClass().getName() + " - " + e.getLocalizedMessage());
}
}
打印这样的错误消息:
Error: java.lang.NullPointerException – null
如果一个对象实例有为null的可能,正确的做法是使用ofNullable。
我们用isPresent方法检测Optional包裹的对象实例是否是null。
下列第28行代码会返回false,因为p2这个Optional实例包裹的person对象为null,而第31行返回true,因为其包裹的对象实例jerry是我于30行在堆上创建的。
Optional
p2 = Optional.ofNullable(person);
System.out.println(p2.isPresent());
Person jerry = new Person("Jerry");
Optional
p3 = Optional.ofNullable(jerry);
System.out.println(p3.isPresent());例2
看到这里,您也许会发问,这个isPresent方法和Java 8之前手动用if ( XXX != null )实际思路类似啊,不都是要程序员自己写代码检测么?
我们看下面的例子。Java 8之前,要调用一个对象实例的方法,我们得先确保该对象实例不为null:
if ( person != null ) {
person.greet();
}
Java 8里的写法就简洁多啦,由3行精简到1行。
System.out.println("p2 test");
p2.ifPresent((p) -> p.greet());
System.out.println("p3 test");
p3.ifPresent((p) -> p.greet());
从上图可以看出,ifPresent方法可以接收一个箭头函数作为输入,语义上也非常清楚:如果Optional实例包裹的对象实例不为null,则执行传入的箭头函数。箭头函数是JavaScript里ES6的习惯称呼,在Java里我们也称其为Lambda表达式。例3
自然而然的,我们会问这个问题,那如果Optional实例包裹的对象实例确实为null呢?我们能指定一些在这种情况下的处理逻辑么?能!
看下图42行,是Java 8之前的传统做法:使用一个三元表达式,如果person实例不为null,返回person实例本身。否则新建一个实例。
第43和第44行用了Optional类的orElse方法,如果Optional包裹的对象实例为null,orElse方法就会返回其传入的对象实例。看看43行和第44行,从语义上说是不是比第42行的三元表达式更清晰?
System.out.println("Example 3");
// before Jave8
Person oldImplementation = ( person != null? person:new Person("Ji"));
Person newPerson = p2.orElse(new Person("Ji"));
Person existPerson = p3.orElse(new Person("Mr Unknown"));
newPerson.greet();
existPerson.greet();例4 - 高级用法
假设对于一个Person实例,我们想做两件事情:
1. 检测这个person是否是Jerry。通过比较其属性name来确认。
2. 如果是Jerry,打印一个字符串,比如"Jerry found".
下图52~54行是旧式写法:在调用jerry.getName()之前先要判断jerry是否为null,很麻烦。
55和56为新式写法。首先传入一个箭头函数到Optional的filter方法里。filter方法无论成功与否,均会返回一个Optional实例。此时,我们就可以应用到前面例2学到的知识啦:对filter返回的Optional实例再次调用ifPresent。如果filter执行成功,则返回的Optional实例包裹的person实例不为null,则会执行ifPresent里传入的箭头函数进行打印。这里也使用到了Java里的链式调用。
希望这4个小例子帮助大家对Java 8里Optional的用法有个最基本的理解。如今Java 10都出来好久了,大家赶快学点新东西吧。
| 留言与评论(共有 0 条评论) |