# Java `finally`块 - 异常处理

> 原文： [https://beginnersbook.com/2013/04/java-finally-block/](https://beginnersbook.com/2013/04/java-finally-block/)

在之前的教程中，我介绍了[`try-catch`块](https://beginnersbook.com/2013/04/try-catch-in-java/)和[嵌套的`try`块](https://beginnersbook.com/2013/04/nested-try-catch/)。在本指南中，我们将看到`finally try`与`try-catch`一起使用。

**`finally`块**包含所有必须执行的关键语句，无论是否发生异常。无论 try 块是否发生异常，例如关闭连接，流等，此块中的语句将始终执行。

## `finally`块的语法

```java
try {
    //Statements that may cause an exception
}
catch {
   //Handling exception
}
finally {
   //Statements to be executed
}
```

## `finally`块的简单示例

在这里你可以看到异常发生在`try`块中，它已经在`catch`块中被处理，在`finally`块被执行之后。

```java
class Example
{
   public static void main(String args[]) {
      try{  
	 int num=121/0;  
	 System.out.println(num);  
      }  
      catch(ArithmeticException e){
         System.out.println("Number should not be divided by zero");
      }  
      /* Finally block will always execute
       * even if there is no exception in try block
       */
      finally{
	 System.out.println("This is finally block");
      }  
      System.out.println("Out of try-catch-finally");  
   }   
}
```

**输出：**

```java
Number should not be divided by zero
This is finally block
Out of try-catch-finally
```

## `finally`块的几个重点

1.  `finally`块必须与`try`块相关联，如果没有`try`块，则不能使用`finally`块。您应该将这些语句放在必须始终执行的块中。

2.  `finally`块是可选的，正如我们在前面的教程中看到的那样，`try-catch`块足以用于[异常处理](https://beginnersbook.com/2013/04/java-exception-handling/)，但是如果你放置一个`finally`块，那么它总是在执行`try`块后运行。

3.  在正常情况下，当`try`块中没有异常时，则在`try`块之后执行`finally`块。但是，如果发生异常，则在`finally`块之前执行`catch`块。

4.  `finally`块中的异常行为与任何其他异常完全相同。

5.  即使`try`块包含诸如`return`，`break`或`continue`之类的控制转移语句，`finally`块中的语句最终也会执行。
让我们看一个例子，看看当`try`块中存在`return`语句时最终是如何工作的：

### `finally`块和`return`语句的另一个例子

你可以看到，即使我们在方法中有`return`语句，`finally`块仍然会运行。

```java
class JavaFinally
{
   public static void main(String args[])
   {
      System.out.println(JavaFinally.myMethod());  
   }
   public static int myMethod()
   {
      try {
        return 112;
      }
      finally {
        System.out.println("This is Finally block");
        System.out.println("Finally block ran even after return statement");
      }
   }
}
```

**以上程序的输出：**

```java
This is Finally block
Finally block ran even after return statement
112
```

要查看`finally`和`return`的更多示例，请参阅： [Java `finally`块和返回语句](https://beginnersbook.com/2013/05/java-finally-return/)。

## `finally`块未执行时的情况

阻止在`finally`块中执行代码的情况是：

- 线程的死亡
- 使用`System.exit()`方法。
- 由于`finally`块中出现异常。

## `finally`和`close()`

`close()`语句用于关闭程序中的所有打开流。在`finally`块中使用`close()`是一个很好的做法。由于即使发生异常，最终块也会执行，因此无论是否发生异常，您都可以确保所有输入和输出流都已正确关闭。

例如：

```java
....
try{ 
    OutputStream osf = new FileOutputStream( "filename" );
    OutputStream osb = new BufferedOutputStream(opf);
    ObjectOutput op = new ObjectOutputStream(osb);
    try{
       output.writeObject(writableObject);
    }
    finally{
       op.close();
    }
}
catch(IOException e1){
     System.out.println(e1);
}
...
```

## 没有`catch`的`finally`块

可以在没有`catch`块的情况下使用`try-finally`块。这意味着`try`块可以在没有`catch`块的情况下使用。

```java
...
InputStream input = null;
try {
    input = new FileInputStream("inputfile.txt");
} 
finally {
    if (input != null) {
       try {
         in.close();
       }catch (IOException exp) {
           System.out.println(exp);
        }
    }
}
...
```

## `finally`块和`System.exit()`

`System.exit()`语句的行为与`return`语句不同。与`return`语句不同，每当在`try`块中调用`System.exit()`时，`finally`块不会执行。这是一个代码片段，演示了相同的代码：

```java
....
try {
   //try block
   System.out.println("Inside try block");
   System.exit(0)
}
catch (Exception exp) {
   System.out.println(exp);
}
finally {
   System.out.println("Java finally block");
}
....
```

在上面的例子中，如果`System.exit(0)`被调用而没有任何异常，那么最终将不会执行。但是，如果在调用`System.exit(0)`时发生任何异常，则将执行`finally`块。

## `try-catch-finally`块

*   `try`语句应该与`catch`块或`finally`相关联。
*   由于`catch`执行异常处理并最终执行清理，因此最好的方法是同时使用它们。

**语法：**

```java
try {
     //statements that may cause an exception
}
catch (…)‏ {
     //error handling code
}
finally {
    //statements to be executed
}
```

### `try-catch-finally`块的例子

**示例 1：**以下示例演示了`try`块中没有异常时`finally`块的工作情况

```java
class Example1{
  public static void main(String args[]){
    try{
       System.out.println("First statement of try block");
       int num=45/3;
       System.out.println(num);
    }
    catch(ArrayIndexOutOfBoundsException e){
       System.out.println("ArrayIndexOutOfBoundsException");
    }
    finally{
       System.out.println("finally block");
    }
    System.out.println("Out of try-catch-finally block");
  }
}
```

**输出：**

```java
First statement of try block
15
finally block
Out of try-catch-finally block
```

**示例 2：**此示例显示了在`try`块中发生异常但在`catch`块中未处理时`finally`块的工作：

```java
class Example2{
   public static void main(String args[]){
     try{
        System.out.println("First statement of try block");
        int num=45/0;
        System.out.println(num);
     }
     catch(ArrayIndexOutOfBoundsException e){
        System.out.println("ArrayIndexOutOfBoundsException");
     }
     finally{
        System.out.println("finally block");
     }
     System.out.println("Out of try-catch-finally block");
   }
}
```

**输出：**

```java
First statement of try block
finally block
Exception in thread "main" java.lang.ArithmeticException: / by zero
at beginnersbook.com.Example2.main(Details.java:6)
```

正如您所看到的那样，系统生成了异常消息，但在此之前，`finally`块已成功执行。

**例 3** ：当`try`块发生异常并在`catch`块中正确处理时

```java
class Example3{
   public static void main(String args[]){
      try{
         System.out.println("First statement of try block");
         int num=45/0;
         System.out.println(num);
      }
      catch(ArithmeticException e){
         System.out.println("ArithmeticException");
      }
      finally{
         System.out.println("finally block");
      }
      System.out.println("Out of try-catch-finally block");
   }
}
```

**输出：**

```java
First statement of try block
ArithmeticException
finally block
Out of try-catch-finally block
```