Java异常处理只有Try-Catch吗?( 二 )


try (Connection connection = dataSource.getConnection){ String updateNameSql = "UPDATE employees SET name=? WHERE emp_id=?"; PreparedStatement preparedStatement = connection.prepareStatement(updateNameSql);} catch (SQLException ex){//..}Java 确保我们 Connection 在执行代码后将其关闭 。在进行此构建之前,我们必须显式地关闭 finally 块中的资源 。
方法 2:Try + Finally
finally 块在任何情况下都将执行 。例如在成功情况下或在异常情况下 。在其中,你需要放置将在之后执行的代码:
FileReader reader = null;try { reader = new FileReader("/text.txt"); int i=0; while(i != -1){ i = reader.read(); System.out.println((char) i); }} catch(IOException ex1){//...} finally{ if(reader != null){ try { reader.close(); } catch (IOException ex2) { //... } }}请注意,此方法有一个缺点:如果在 finally 块内引发异常 ,则会使其中断 。因此,我们必须正常处理异常 。将 try-with-resources 与可关闭的资源一起使用,避免在 finally 块内关闭资源。
方法 3:多 Catch 块
最后,Java 允许我们使用一个 try-catch 块多次捕获异常 。当方法抛出几种类型的异常并且您想区分每种情况的逻辑时,这很有用 。举个例子,让这个虚构的类使用抛出多个异常的方法:
class Repository{ void insert(Car car) throws DatabaseAccessException, InvalidInputException { //... }}//...try { repository.insert(car);} catch (DatabaseAccessException dae){ System.out.println("Database is down!");} catch (InvalidInputException iie){ System.out.println("Invalid format of car!");}在这里需要记住什么?通常,我们假设在此代码中,这些异常处于同一级别 。但是你必须从最具体到最一般的顺序排序 catch 块 。例如,捕获 ArithmeticException 异常必须在 捕获 Exception 异常之前 。
到这里,我们已经回顾了如何使用内置方法处理 Java 中的异常 。现在,让我们看一下如何使用 Vavr 库执行此操作 。
Vavr Try我们回顾了捕获 Java 异常的标准方法 。另一种方法是使用 Vavr Try 类,Vavr 是 Java 8+ 中一个函数式库,提供了一些不可变数据类型及函数式控制结构 。首先,添加 Vavr 库依赖项:
<dependency> <groupId>io.vavr</groupId> <artifactId>vavr</artifactId> <version>0.10.2</version></dependency>Try 容器
Vavr 包含的 Try 类是 monadic 容器类型,它表示可能导致异常或返回成功计算出的值的计算 。此结果可以采用 Success 或 Failure 。看下面这段代码:
class CarsRepository{ Car insert(Car car) throws DatabaseAccessException { //... } Car find (String id) throws DatabaseAccessException { //.. } void update (Car car) throws DatabaseAccessException { //.. } void remove (String id) throws DatabaseAccessException { //.. }}在调用此代码时,我们将使用这些 try-catch 块来处理 DatabaseAccessException 。但是另一个解决方案是使用 Vavr 对其进行重构 。查看以下代码片段:
class CarsVavrRepository{ Try<Car> insert(Car car) { System.out.println("Insert a car..."); return Try.success(car); } Try<Car> find (String id) { System.out.println("Finding a car..."); System.out.println("..something wrong with database!"); return Try.failure(new DatabaseAccessException()); } Try<Car> update (Car car) { System.out.println("Updating a car..."); return Try.success(car); } Try<Void> remove (String id) { System.out.println("Removing a car..."); System.out.println("..something wrong with database!"); return Try.failure(new DatabaseAccessException()); }}现在,我们可以使用 Vavr 处理数据库问题 。
处理成功
当我们收到成功计算的结果时,我们会收到 Success:
@Testvoid successTest(){ CarsVavrRepository repository = new CarsVavrRepository(); Car skoda = new Car("skoda", "9T4 4242", "black"); Car result = repository.insert(skoda).getOrElse(new Car("volkswagen", "3E2 1222", "red")); Assertions.assertEquals(skoda.getColor(), result.getColor()); Assertions.assertEquals(skoda.getId(), result.getId());}请注意,Vavr.Try 相较于 Vavr.Option,为我们提供了一种方便的 getOrElse 方法,在发生故障的情况下我们可以使用默认值,我们可以将这种逻辑与有问题的方法结合使用,例如与 find 一起使用 。
处理失败
在另一种情况下,我们将处理 Failure:
@Testvoid failureTest(){ CarsVavrRepository repository = new CarsVavrRepository(); // desired car Car bmw = new Car("bmw", "4A1 2019", "white"); // failure car Car failureCar = new Car("seat", "1A1 3112", "yellow"); Car result = repository.find("4A1 2019").getOrElse(failureCar); Assertions.assertEquals(bmw.getColor(), result.getColor()); Assertions.assertEquals(bmw.getId(), result.getId());}


推荐阅读