Java Optional实践(小结)

 更新时间:2018年09月25日 09:04:43   作者:张喜硕  
这篇文章主要介绍了Java Optional实践(小结),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

问题描述

在大热的Spring Boot 2.0中,在将原来的泛型改为了Optional,旨在让我们的代码更简洁。

实践

Optional

很简单的一个类,点开它的源代码,其中所有的方法都是与null相关联的。

这是一个简化我们处理null的类。

它就是一个容器,其中有我们想要的对象,但是该对象有时候会是空,所以我们需要使用Optional封装好的方法来获取需要的对象。从而很好地避免了空指针异常。

错误示范

我看到网上很多人这么写:

catRepository.findById(id).get();

下面是Spring Boot 1.5的写法,那请问:如果上面的写法是正确的,那为什么还要大费周章设计一个Optional呢?

catRepository.findOne(id);

分析

通过get是能获取到我们需要的对象。

但是看看get的源代码,这样写,抛出了NoSuchElementException异常,这个异常我们没法在全局中处理它。

public T get() {
  if (value == null) {
    throw new NoSuchElementException("No value present");
  }
  return value;
}

为什么不能再全局中处理呢?大家可以思考一下:

因为NoSuchElementException覆盖的范围太广了,只要是Optional中有null就会抛出NoSuchElementException,很多情况下都会造成这种异常,那我们究竟要给用户一个什么样的提示信息好呢?最后还是给出500服务器异常,那异常处理的意义何在呢?

所以我们需要用Optional来抛出一个有特定范围的能被全局准确处理的异常。

Cat cat = catRepository.findOne(id);
if (null == cat) {
  throw new EntityNotFoundException("该实体找不到");
}
return cat;

思想都是一样,我们不过是用一种更简洁的写法实现上面的功能。

实现

没错,就像下面一样,我们只需要一行代码!

public Cat findById(Long id) {
  return catRepository.findById(id).orElseThrow(EntityNotFoundException::new);
}

findById返回一个Optional,然后调用该对象的orElseThrow方法。

orElseThrow方法,如果存在,返回包含的值,否则抛出异常。

该方法的参数是一个lamda表达式。这里就不深究lamda表达式的几种类型了,如果感兴趣可以自行研究下FunctionConsumerPredicateSupplier这四个函数式接口的区别。

所以传一个lamda表达式进去,然后IDEA会给出警告:

Can be replaced with method reference

lamda表达式能被一个方法引用代替,Alt + Enter,我们最终的代码就长这样:

这里的::lamda表达式的一种简写,是Java8中的新特性,看着可能有点奇怪,原来,编译器比程序员聪明多了。

异常处理

@RestControllerAdvice
public class GlobalExceptionHandler {

  @ExceptionHandler(EntityNotFoundException.class)
  public ResponseEntity<String> entityNotFoundHandler() {
    return new ResponseEntity<>("您要找的实体不存在", HttpStatus.NOT_FOUND);
  }
}

写个控制器增强,全局处理异常,这里的RestControllerAdvice又是一个组合注解:

处理异常,同时以Json的格式返回。

@Test
public void findById() throws Exception {
  this.mockMvc.perform(get("/cat/1"))
      .andDo(print());
}

写个控制器的单元测试,查询一个不存在的实体,运行,看控制台的打印输出:

一劳永逸

一劳永逸,这是我们最喜欢的东西了。

return catRepository.findById(id).orElseThrow(EntityNotFoundException::new);

以后再查询,就这一行,再也不用去判断null了。

NotNull

正所谓条条大路通罗马,对null的一劳永逸,我们这样实现,别人也可以那样实现。

如果你在Spring的项目中打过断点调试的话,那我断定你一定见过下面这行代码:

Assert.notNull();

以下是该方法的源码,注意这里的Assertorg.springframework.util包下的:

刚方法用于判断null,如果为空,则抛出异常。

随便点开一个方法,都会在第一行为不该为null的参数进行判断。

这里,不禁对整个框架肃然起敬,同样一个方法,大牛写了二十分钟,而你写了十分钟,但是你却去改了半个小时的bug

@Nullable

可能在上面看到了我们不熟悉的注解@Nullable,表示从来没见过,这个注解干什么用的呢?

万能的StackOverflow又给出了完美的回答:

这会让你的代码更清晰,如果你重写这个方法,你也需要让参数可为空。通常也用于代码提示。

@Nullable@NotNull这一对注解,没什么实际意义,只是用于代码更清晰,同时编译器能给出我们提示。

总结

之前一直抱怨Java更新的太快,学校教的是Java5之前的东西,从Java5开始有的注解,但是从来没讲过这个东西,然而去看看官方的描述:

其实,Java的每次更新,都是为了我们更简洁优雅的代码而努力。去看看官方的描述,Java让我们将更多的精力放在think上,而不是code上。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Java使用Tess4J实现图像识别方式

    Java使用Tess4J实现图像识别方式

    这篇文章主要介绍了Java使用Tess4J实现图像识别方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • 如何在springMVC的controller中获取request

    如何在springMVC的controller中获取request

    这篇文章主要介绍了如何在springMVC的controller中获取request,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • Java 超详细讲解十大排序算法面试无忧

    Java 超详细讲解十大排序算法面试无忧

    这篇文章主要介绍了Java常用的排序算法及代码实现,在Java开发中,对排序的应用需要熟练的掌握,这样才能够确保Java学习时候能够有扎实的基础能力。那Java有哪些排序算法呢?本文小编就来详细说说Java常见的排序算法,需要的朋友可以参考一下
    2022-04-04
  • Java中FileOutputStream流的write方法

    Java中FileOutputStream流的write方法

    这篇文章主要为大家详细介绍了Java中FileOutputStream流的write方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • drools中then部分的写法(推荐)

    drools中then部分的写法(推荐)

    本文介绍一下drools中then部分的写法,以及一些内置的方法,比如insert/delete/modify等等。同时也介绍一下rule的继承,和在when中实现if else if 等操作,感兴趣的朋友跟随小编一起看看吧
    2022-05-05
  • Java中的Optional使用详细说明

    Java中的Optional使用详细说明

    这篇文章主要介绍了Java中的Optional使用详细说明,Optional就是相当于把对象包了一层,将判断空的部分代码给单独抽出来了,主要就是为了避免null引起的部分问题,需要的朋友可以参考下
    2023-11-11
  • SpringMVC的组件之HandlerExceptionResolver详解

    SpringMVC的组件之HandlerExceptionResolver详解

    这篇文章主要介绍了SpringMVC的组件之HandlerExceptionResolver详解,不管是在处理请求映射(HandlerMapping),还是在请求被处理(Handler)时抛出的异常,DispatcherServlet都会委托给HandlerExceptionResolver进行异常处理,该接口只有一个方法,需要的朋友可以参考下
    2023-10-10
  • SpringBoot 启动报错Unable to connect to Redis server: 127.0.0.1/127.0.0.1:6379问题的解决方案

    SpringBoot 启动报错Unable to connect to 

    这篇文章主要介绍了SpringBoot 启动报错Unable to connect to Redis server: 127.0.0.1/127.0.0.1:6379问题的解决方案,文中通过图文结合的方式给大家讲解的非常详细,对大家解决问题有一定的帮助,需要的朋友可以参考下
    2024-10-10
  • 深入浅出的讲解Java关键字final的作用

    深入浅出的讲解Java关键字final的作用

    final是Java中非常常见的一个关键字,可以说每天都在使用它,虽然常见,但却也不见得都那么显而易见,今天就来研究一下final,以加深对它的理解和更合理的运用,需要的朋友可以参考下
    2023-06-06
  • 使用FeignClient调用远程服务时整合本地的实现方法

    使用FeignClient调用远程服务时整合本地的实现方法

    这篇文章主要介绍了使用FeignClient调用远程服务时整合本地的实现方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03

最新评论