Skip to content

Commit d2b7f29

Browse files
committed
add: try-with-resources
1 parent 683ac6e commit d2b7f29

2 files changed

Lines changed: 97 additions & 0 deletions

File tree

documents/.vuepress/const.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ exports.JavaList = [
4141
"Java/자바-프로그램이-실행되는-흐름.md",
4242
"Java/JCF-자료구조의-초기-용량을-지정하면-좋은-점.md",
4343
"Java/제네릭의-공변,-반공변,-무공변.md",
44+
"Java/try-with-resources.md",
4445
];
4546

4647
exports.OperatingSystemList = [
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# try-with-resources
2+
3+
* 커넥션, 입출력 스트림 등과 같은 자원을 사용한 후 자동으로 해제하는 기능
4+
* java 7 부터 도입되었고, 자원 해제로 성능 문제 및 메모리 누수 방지 가능
5+
* try-with-resources가 정상적으로 작동하려면 `AutoClosable` 인터페이스를 구현한 객체를 사용해야 하며, `try()` 괄호 내에서 변수를 선언해야 함
6+
```java
7+
try (BufferedReader br = new BufferedReader(new FileReader("path"))) {
8+
return br.readLine();
9+
} catch (IOException e) {
10+
return null;
11+
}
12+
```
13+
14+
## try-catch-finally 대신 try-with-resources를 사용해야 하는 이유
15+
```java
16+
BufferedReader br = null;
17+
try {
18+
br = new BufferedReader(new FileReader("path"));
19+
return br.readLine();
20+
} catch (IOException e) {
21+
return null;
22+
} finally {
23+
if (br != null) {
24+
try {
25+
br.close();
26+
} catch (IOException e) {
27+
e.printStackTrace();
28+
}
29+
}
30+
}
31+
```
32+
* try-catch-finally 사용 시 finally 블록에서 `close()`를 명시적으로 호출해야 함
33+
* `close()` 호출을 누락하거나 이 과정에서 다른 예외가 또 발생하면 예외 처리가 복잡해짐
34+
* 또한 여러 개의 자원을 다를 경우, 먼저 호출한 자원의 `close()`에서 예외가 발생하면 다음 자원의 `close()` 호출을 위해서 추가적인 try-catch-finally가 필요하기 때문에 가독성이 떨어지고 실수할 가능성이 높음
35+
36+
### try-with-resources를 사용하면
37+
* try 블록이 종료될 때 `close()`를 자동으로 호출해서 자원을 해제
38+
* finally 블록 없이도 자원을 안전하게 정리하기 때문에 코드가 간결해짐
39+
* try 문에서 여러 자원을 선언하면, 선언된 반대 순서로 자동 해제됨
40+
41+
## Suppressed Exception
42+
* Suppressed Exception이란 억제된 예외로, 예외가 발생했지만 무시되는 예외를 의미
43+
* try-with-resources는 `close()` 과정에서 발생한 예외를 Suppressed Exception으로 관리함
44+
```java
45+
class CustomResource implements AutoCloseable {
46+
47+
@Override
48+
public void close() throws Exception {
49+
throw new Exception("Close Exception 발생");
50+
}
51+
52+
void process() throws Exception {
53+
throw new Exception("Primary Exception 발생");
54+
}
55+
}
56+
57+
public class Main {
58+
59+
public static void main(String[] args) throws Exception {
60+
try (CustomResource resource = new CustomResource()) {
61+
resource.process();
62+
}
63+
}
64+
}
65+
66+
Exception in thread "main" java.lang.Exception: Primary Exception 발생
67+
at CustomResource.process(CustomResource.java:9)
68+
at Main.main(Main.java:5)
69+
Suppressed: java.lang.Exception: Close Exception 발생
70+
at CustomResource.close(CustomResource.java:5)
71+
at Main.main(Main.java:4)
72+
```
73+
* Suppressed Exception를 사용하면 원래 예외(Primary Exception)을 유지하면서 추가 예외도 함께 추적 가능
74+
* try-catch-finally는 `close()`를 호출할 때 예외가 발생하면 원래 예외가 사라지고 `close()`에서 발생한 예외만 남을 수 있음
75+
```java
76+
public class Main {
77+
78+
public static void main(String[] args) throws Exception {
79+
CustomResource resource = null;
80+
try {
81+
resource = new CustomResource();
82+
resource.process();
83+
} finally {
84+
if (resource != null) {
85+
resource.close();
86+
}
87+
}
88+
}
89+
}
90+
Exception in thread "main" java.lang.Exception: Close Exception 발생
91+
at CustomResource.close(CustomResource.java:5)
92+
at Main.main(Main.java:16)
93+
```
94+
* 이처럼 원래 예외가 사라지면 디버깅이 어려워질 수 있음
95+
* Throwable의 `addSuppressed()`로 최종적으로 던질 예외를 제외한 예외들을 억제된 예외로 추가 가능
96+
* 하지만 코드가 더욱 복잡해지기 때문에 try-with-resources를 사용하는 것이 좋음

0 commit comments

Comments
 (0)