File: Finally.md

package info (click to toggle)
error-prone-java 2.18.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 23,204 kB
  • sloc: java: 222,992; xml: 1,319; sh: 25; makefile: 7
file content (48 lines) | stat: -rw-r--r-- 1,510 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
Terminating a finally block abruptly preempts the outcome of the try and catch
blocks, and will cause the result of any previously executed return or throw
statements to be ignored. Finally blocks should be written so they always
complete normally.

Consider the following code. In the case where `doWork` throws `SomeException`,
the finally block will still be executed. If closing the input stream *also*
fails, then the exception that was thrown in the catch block will be prempted by
the exception thrown by `close()`, and the first exception will be lost.

```java
InputStream in = openInputStream();
try {
  doWork(in);
} catch (SomeException e) {
  throw new SomeError(e);
} finally {
  in.close(); // exception could be thrown here
}
```

This code is easily fixed using try-with-resources. Below, the input stream will
always be closed, and if `doWork` fails and an `IOException` is thrown, then the
try-with-resources uses the `Throwable.addSuppressed()` method added in Java 7
to propagate both exceptions back to the caller.

```java
try (InputStream in = openInputStream()) {
  doWork(in);
} catch (SomeException e) {
  throw new SomeError(e);
}
```

If Java 7 is not available, we recommend Guava's
[Closer API](https://guava.dev/releases/snapshot/api/docs/com/google/common/io/Closer.html).

```java
Closer closer = Closer.create();
try {
  InputStream in = closer.register(openInputStream());
  doWork(in);
} catch (Throwable e) {
  throw closer.rethrow(e);
} finally {
  closer.close();
}
```