问题描述
在大热的Spring Boot 2.0中,在将原来的泛型改为了Optional,旨在让我们的代码更简洁。
实践
Optional
很简单的一个类,点开它的源代码,其中所有的方法都是与null相关联的。
这是一个简化我们处理null的类。
它就是一个容器,其中有我们想要的html" target="_blank">对象,但是该对象有时候会是空,所以我们需要使用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表达式的几种类型了,如果感兴趣可以自行研究下Function、Consumer、Predicate、Supplier这四个函数式接口的区别。
所以传一个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();
以下是该方法的源码,注意这里的Assert是org.springframework.util包下的:
刚方法用于判断null,如果为空,则抛出异常。
随便点开一个方法,都会在第一行为不该为null的参数进行判断。
这里,不禁对整个框架肃然起敬,同样一个方法,大牛写了二十分钟,而你写了十分钟,但是你却去改了半个小时的bug。
@Nullable
可能在上面看到了我们不熟悉的注解@Nullable,表示从来没见过,这个注解干什么用的呢?
万能的StackOverflow又给出了完美的回答:
这会让你的代码更清晰,如果你重写这个方法,你也需要让参数可为空。通常也用于代码提示。
@Nullable和@NotNull这一对注解,没什么实际意义,只是用于代码更清晰,同时编译器能给出我们提示。
总结
之前一直抱怨Java更新的太快,学校教的是Java5之前的东西,从Java5开始有的注解,但是从来没讲过这个东西,然而去看看官方的描述:
其实,Java的每次更新,都是为了我们更简洁优雅的代码而努力。去看看官方的描述,Java让我们将更多的精力放在think上,而不是code上。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
问题内容: 我正在阅读 http://www.alexrothenberg.com/2013/02/11/the-magic-behind-angularjs- dependency-injection.html ,事实证明,如果您缩小JavaScript的大小,angularjs依赖项注入会出现问题,我想知道是否 你应该使用 总而言之,我认为第二个片段是针对angularjs的旧版本的,但是..
本文向大家介绍Node.js服务Docker容器化应用实践小结,包括了Node.js服务Docker容器化应用实践小结的使用技巧和注意事项,需要的朋友参考一下 本篇不会讲解 Docker 命令的使用、安装等,因为在之前一篇文章一文零基础教你学会 Docker 入门到实践中也已经讲解的很详细了,不清楚的可以点击链接回头在重新看下,本篇重点是介绍 Node.js 项目如何进行 Docker 容器化及一
熟悉常见的坏实践能帮助我们理解React是如何工作的并且给我们重构代码提供不错的指导.
Subversion实践 是时候从抽象转到具体了,在本小节,我们会展示一个Subversion真实使用的例子。 Subversion版本库URL 正如我们在整本书里描述的,Subversion使用URL来识别Subversion版本库中的版本化资源,通常情况下,这些URL使用标准的语法,允许服务器名称和端口作为URL的一部分: $ svn checkout http://svn.example.
实用的EAP 在本节中,我们将在FreeRADIUS安装上测试各种EAP方法。 为此,我们使用JRadius Simulator。 该程序是JRadius框架的一部分,也是Coova提供的众多项目之一。 JRadius Simulator用于通过向FreeRADIUS发送EAP请求来模拟NAS。 这消除了对专用NAS(认证者)和客户端(请求者)测试EAP方法的需要。
CMake 已经开发了 5,6 年的时间,如果没有 KDE4,也许不会有人或者 Linux 发行版本重视 CMake,因为除了 Kitware 似乎没有人使用它。 随书源代码:https://www.wenjiangs.com/wp-content/uploads/2020/12/cmake.zip PDF 版本:https://www.wenjiangs.com/wp-content/uploa