Java 7 try-with-resources 구문 (ARM 블록 ( Automatic Resource Management ) 이라고도 함 )은 하나의 AutoCloseable
자원 만 사용할 때 훌륭하고 짧으며 간단 합니다. 그러나 서로 의존하는 여러 리소스를 선언해야 할 때 올바른 관용구가 무엇인지 확실하지 않습니다 (예 : a FileWriter
및 a) BufferedWriter
. 물론이 질문 AutoCloseable
은이 두 가지 특정 클래스뿐만 아니라 일부 리소스가 래핑 된 경우에도 관련이 있습니다.
나는 다음 세 가지 대안을 생각해 냈습니다.
1)
내가 본 순진한 관용구는 ARM 관리 변수에서 최상위 래퍼 만 선언하는 것입니다.
static void printToFile1(String text, File file) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
이것은 좋고 짧지 만 깨졌습니다. 기본 FileWriter
변수는 변수에 선언되어 있지 않으므로 생성 된 finally
블록 에서 직접 닫히지 않습니다 . close
랩핑 방법을 통해서만 닫힙니다 BufferedWriter
. 문제는 bw
의 생성자 에서 예외가 발생 close
하면 호출되지 않으므로 기본 FileWriter
이 닫히지 않는다는 것 입니다.
2)
static void printToFile2(String text, File file) {
try (FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw)) {
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
여기서 기본 리소스와 래핑 리소스는 모두 ARM 관리 변수에서 선언되므로 두 변수 모두 확실히 닫히지 만 기본 fw.close()
은 래핑을 통해 직접뿐만 아니라 래핑을 통해 두 번 호출됩니다bw.close()
.
계약에 여러 호출 이 허용되는 두 가지 특정 클래스 Closeable
(하위 유형 AutoCloseable
)를 구현하는 두 가지 특정 클래스에 대해서는 문제가되지 않습니다 close
.
이 스트림을 닫고 이와 관련된 모든 시스템 리소스를 해제합니다. 스트림이 이미 닫혀 있으면이 메소드를 호출해도 효과가 없습니다.
그러나, 일반적인 경우에, 난 단지 구현 자원을 가질 수있다 AutoCloseable
(그리고를 Closeable
보장하지 않습니다), close
여러 번 호출 할 수 있습니다 :
java.io.Closeable의 close 메소드와 달리이 close 메소드는 dem 등성이 될 필요는 없습니다. 다시 말해,이 close 메소드를 두 번 이상 호출하면 Closeable.close와는 달리 한 번 이상 호출해도 아무런 영향을 미치지 않는 부작용이있을 수 있습니다. 그러나이 인터페이스의 구현자는 가까운 메소드를 dem 등원으로 만들 것을 강력히 권장합니다.
삼)
static void printToFile3(String text, File file) {
try (FileWriter fw = new FileWriter(file)) {
BufferedWriter bw = new BufferedWriter(fw);
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
이 버전은 이론적으로 정확해야합니다. 왜냐하면이 버전 만 fw
정리해야하는 실제 자원을 나타 내기 때문 입니다. 는 bw
받는 사람, 그것은 단지 대표를 어떤 자원을 보유하지 자체 않습니다 fw
단지 가까이 기본에 충분해야한다, 그래서 fw
.
반면에 구문은 약간 불규칙하며 Eclipse는 경고를 발행하는데, 이는 잘못된 알람이라고 생각하지만 여전히 처리해야 할 경고입니다.
리소스 누출 : 'bw'는 닫히지 않습니다
그렇다면 어떤 접근법을 사용해야할까요? 아니면 올바른 다른 관용구를 놓쳤 습니까?
public BufferedWriter(Writer out, int sz)
를 들어을 던질 수 있습니다 IllegalArgumentException
. 또한 생성자에서 무언가를 던지거나 필요한 사용자 정의 래퍼를 만드는 클래스로 BufferedWriter를 확장 할 수 있습니다.
BufferedWriter
생성자는 쉽게 예외를 던질 수 있습니다. OutOfMemoryError
아마도 버퍼에 적절한 메모리 청크를 할당 할 때 가장 일반적 일 것입니다 (전체 프로세스를 다시 시작하려고 할 수도 있음). / 당신은 필요 flush
당신 BufferedWriter
이 닫지 말고 내용 (일반적으로 유지하려는 경우 에만 이 아닌 예외 케이스). FileWriter
"기본"파일 인코딩으로 발생하는 모든 것을 선택합니다. 명시 적으로 작성하는 것이 좋습니다.