我们的业务代码中,最常见的一个操作就是卫语句保护,接口先对进来的参数进行判空,再执行后续动作,然后再对得到的结果进行判空,再处理逻辑;为了不让代码抛出NullPointerException要步步小心谨慎,案例如下:
-
Java 代码01if (StringUtil.isEmpty(userID)) {
02 return new ResponseObject().failure("userID is null!!!");
03}
04if (versionInfo == null) {
05 return new ResponseObject().failure("Add version failed!Miss version information !");
06}
07VersionInfo result = versionServer.addOrUpdateVersion(userID, versionInfo);
08if (StringUtil.isNotEmpty(versionInfo.getVersionConfigMessage())) {
09 return new ResponseObject().failure(versionInfo.getVersionConfigMessage());
10}
11if (result == null) {
12 return new ResponseObject().failure("Query version failed!");
13}
这样的代码不但很不优雅,而且风险极大,一旦开发者忘记进行null的判断,就有让程序挂掉的风险。Java8中新增了Optional类解决了这一问题,可对null进行替换。在刚刚结束的产品线编码大赛中,由于对程序的稳定性要求很高,避免出现挂掉的风险,使用了Optional类对各个步骤加强了保障。
如下是一个改造前获取路径的方法:
-
Java 代码1private Path getPath(int startId, int targetId, SystemTime sysTime, List midNodeIds) {
2 Prune prune = new Prune();
3 prune.calcPathByNodeId(startId, targetId, sysTime, midNodeIds);
4 PriorityQueue curPaths = prune.getPathList();
5 if (curPaths.size() == 0) {
6 return null;
7 }
8 return curPaths.peek();
9}
在外面的使用如下:
-
Java 代码1Path path = getPath(startNode.getId(), targetNode.getId(), sysTime, midNodeIds);
2if (path != null) {
3 pathList.add(path);
4}
当然,如果这时候忘记进行null判断了,那么pathList中就加入了一个空对象,后续调用就很可能挂掉。通过Optional改造如下:
-
Java 代码1private Optional getPath(int startId, int targetId, SystemTime sysTime, List midNodeIds) {
2 Prune prune = new Prune();
3 prune.calcPathByNodeId(startId, targetId, sysTime, midNodeIds);
4 PriorityQueue curPaths = prune.getPathList();
5 if (curPaths.size() == 0) {
6 return Optional.empty();
7 }
8 return Optional.of(curPaths.peek());
9}
这里将原来的null和返回的Path分别用empty方法和of方法包了起来,外部调用如下:
-
Java 代码1Optional pathOP = getPath(startNode.getId(), targetNode.getId(), sysTime, midNodeIds);
2if (pathOP.isPresent()) {
3 pathList.add(pathOP.get());
4}
当开发者忘记判断isPresent时,编译器会进行高亮提醒,保证代码的安全
上面的部分知识Optional作为返回参数的包装使用,保证外面的调用者不会遗漏空检查,作为Java8新加入的功能当然不仅仅这么简单,Optional的更强大之处在于支持函数式编程,对于如下连续判断的代码:
-
Java 代码01f (user != null) {
02 Address address = user.getAddress();
03 if (address != null) {
04 Country country = address.getCountry();
05 if (country != null) {
06 String isocode = country.getIsocode();
07 if (isocode != null) {
08 isocode = isocode.toUpperCase();
09 }
10 }
11 }
12}
可优化成:
-
Java 代码1String isocode = user.getAddress().getCountry().getIsocode().toUpperCase();