四个例子学会使用Java8的Optional避免NullPointerException

做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 条评论)
   
验证码:

相关文章

推荐文章

'); })();