Java에서 리소스로 시도 사용 방법

Feb 21 2023
try-with-resource 문을 사용하여 예외를 처리하는 방법 자원을 사용한 Java 시도 구성인 AKA Java 자원 시도는 Java InputStream 또는 JDBC 연결과 같은 리소스 사용을 완료한 경우 자동으로 리소스를 닫을 수 있는 예외 처리 메커니즘입니다. . Oracle은 2011년 Java 언어에 try with resources 구문을 추가하여 네트워크 소켓, 데이터베이스 연결, 파일 및 폴더에 대한 참조와 같은 객체가 사용 후 완전히 종료되도록 보장합니다.

try-with-resource 문을 사용하여 예외를 처리하는 방법

리소스를 사용한 Java 시도 구성, AKA Java try-with-resources 는 작업이 완료되면 Java InputStream 또는 JDBC 연결과 같은 리소스를 자동으로 닫을 수 있는 예외 처리 메커니즘입니다.

Oracle은 2011년 Java 언어에 try with resources 구문을 추가하여 네트워크 소켓, 데이터베이스 연결, 파일 및 폴더에 대한 참조와 같은 객체가 사용 후 완전히 종료되도록 보장했습니다. 개발자가 리소스에 대한 핸들을 연 후 이러한 리소스를 닫지 않으면 메모리 누수가 발생하고 피할 수 있는 가비지 수집 루틴이 트리거되며 서버의 CPU에 무리가 갈 수 있습니다 .

· Java 7 이전
· try-with-resource 문을 사용하는 방법?
· try-with-resource 문을 사용해야 하는 이유는 무엇입니까?
· 예
· 억제된 예외
· try-with-resources 사용의 이점
· 리소스가 여러 개인 try-with-resources
· Java 9 — 효과적인 최종 변수

자바 7 이전

Java에서 입력 또는 출력 스트림과 같은 리소스를 사용하는 경우 사용 후 항상 닫아야 합니다. 또한 예외를 throw할 수 있으므로 try-catch 블록 에 있어야 합니다 . 클로징은 finally 블록 에 있어야 합니다 . 이것은 적어도 Java 7까지의 방법입니다. 여기에는 몇 가지 단점이 있습니다.

  • 리소스 를 닫기 전에 리소스가 null 인지 확인해야 합니다.
  • 닫기 자체에서 예외가 발생할 수 있으므로 마침내 또 다른 try-catch를 포함해야 했습니다.
  • 프로그래머는 리소스를 닫는 것을 잊는 경향이 있습니다.

try-with-resource 문을 사용하는 방법은 무엇입니까?

Java 7에서 처음 도입되었으며 개발자가 하나의 try- catch-finally 블록 에서만 사용하는 리소스에 대한 리소스 관리에 대해 걱정할 필요가 없다는 것이 전체 아이디어입니다 . 이는 개발자가 실제로 리소스를 닫는 데만 사용했던 finally 블록 의 필요성을 제거함으로써 달성됩니다 .

Java에서 try-with-resources 문은 하나 이상의 리소스를 선언하는 try 문입니다. 리소스는 프로그램 종료 후 닫아야 하는 개체입니다. 실행이 try-with-resources 블록을 벗어나면 try-with-resources 블록 내부에서 예외가 발생했는지 또는 종료를 시도할 때 예외가 발생했는지 여부에 관계없이 try-with-resources 블록 내에서 열려 있는 모든 리소스가 자동으로 닫힙니다. 자원.

Java의 try-with-resources 언어 기능을 사용하려면 다음 규칙이 적용됩니다.

  • try with resources 문으로 관리되는 모든 개체는 AutoCloseable 인터페이스를 구현해야 합니다.
  • Java의 try with resources 블록 내에서 여러 AutoCloseable 개체를 만들 수 있습니다.
  • try with resources 문에서 선언된 개체는 try 블록 내에 범위가 있지만 catch 및 finally 블록에는 범위가 없습니다.
  • try with resources 블록에서 선언된 객체의 close() 메서드는 실행 중에 예외가 발생했는지 여부에 관계없이 호출됩니다.
  • close() 메서드에서 예외가 발생하면 억제된 예외 로 분류될 수 있습니다 .

AutoCloseable 개체가 참조하는 리소스는 try with resources 문이 사용되는 경우 항상 닫히며 리소스의 잘못된 할당으로 인해 일반적으로 발생하는 잠재적인 메모리 누수가 제거됩니다.

통사론

try(declare resources here) {
    // use resources
}
catch(FileNotFoundException e) {
    // exception handling
}

간단히 말해서, 자동으로 닫히려면 자원이 try 내에서 선언되고 초기화되어야 합니다 .

try (PrintWriter writer = new PrintWriter(new File("test.txt"))) {
    writer.println("Hello World");
}

새로운 try-with-resources 기능을 사용하는 간단하고 분명한 방법은 기존의 장황한 try-catch-finally 블록을 대체하는 것입니다.

다음 코드 샘플을 비교해 보겠습니다.

첫 번째는 일반적인 try-catch-finally 블록입니다.

Scanner scanner = null;
try {
    scanner = new Scanner(new File("test.txt"));
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if (scanner != null) {
        scanner.close();
    }
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy

try (Scanner scanner = new Scanner(new File("test.txt"))) {
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException fnfe) {
    fnfe.printStackTrace();
}

예외에 관해서는 try-catch-finally 블록과 try-with-resources 블록에 차이가 있습니다. try 블록과 finally 블록 모두에서 예외가 발생하면 메서드는 finally 블록에서 발생한 예외를 반환합니다.

try-with-resources의 경우 try 블록과 try-with-resources 문에서 예외가 발생하면 메소드는 try 블록에서 발생한 예외를 반환합니다. try-with-resources에 의해 발생한 예외는 억제됩니다. 즉, try-with-resources 블록이 억제된 예외를 throw한다고 말할 수 있습니다.

try-with-resource 문을 사용해야 하는 이유는 무엇입니까?

try-with-resources 문은 문 실행이 끝날 때 각 리소스가 닫히도록 합니다 . 리소스를 닫지 않으면 리소스 누수가 발생할 수 있으며 프로그램에서 사용 가능한 리소스를 소진할 수도 있습니다. 그것은 try-catch-finally 블록을 사용할 때 주로 일어난 일입니다.

Java SE 7 이전에는 try 문이 정상적으로 완료되었는지 갑자기 완료되었는지 에 관계없이 finally 블록을 사용하여 리소스가 닫히도록 할 수 있습니다 . 다음 예제에서는 try -with-resources 문 대신 finally 블록을 사용합니다.

static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
   
    FileReader fr = new FileReader(path);
    BufferedReader br = new BufferedReader(fr);
    try {
        return br.readLine();
    } finally {
        br.close();
        fr.close();
    }
}

이 예제에서 readLine 메소드가 예외를 발생시키고 finally 블록 의 br.close() 문이 예외를 발생시키면 FileReader가 누출된 것입니다. 따라서 프로그램 리소스를 닫으려면 finally 블록 대신 try -with-resources 문을 사용하십시오.

예

다음 예제에서는 파일에서 첫 번째 줄을 읽습니다. FileReader 및 BufferedReader 인스턴스를 사용하여 파일에서 데이터를 읽습니다. FileReader 및 BufferedReader 는 프로그램이 완료된 후 닫아야 하는 리소스입니다.

import java.io.*;
class Main {
  public static void main(String[] args) {
    String line;
    try(BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
      while ((line = br.readLine()) != null) {
        System.out.println("Line =>"+line);
      }
    } catch (IOException e) {
      System.out.println("IOException in try block =>" + e.getMessage());
    }
  }
}

억제된 예외

try 블록이 예외를 발생시키고 try-with-resources에서 하나 이상의 예외가 발생하면 try-with-resources에서 발생한 예외가 억제됩니다. 즉, try-with-resources에 의해 throw된 예외는 억제된 예외라고 말할 수 있습니다.

Throwable 클래스의 getSuppress() 메서드를 사용하여 이러한 예외를 가져올 수 있습니다.

예 :

위의 예에서 다음 과 같은 경우 try-with-resources 문에서 예외가 발생할 수 있습니다.

  • test.txt 파일을 찾을 수 없습니다.
  • BufferedReader 개체를 닫습니다 .

try 블록과 try -with-resources 문 모두에서 예외가 발생하면 try 블록의 예외가 발생하고 try-with-resources 문의 예외가 억제됩니다.

억제된 예외 검색

Java 7 이상에서는 try 블록 에서 발생한 예외에서 Throwable.getSuppressed() 메서드를 호출하여 억제된 예외를 검색할 수 있습니다.

getSuppress() try-with-resources 문에 의해 억제된 모든 예외를 포함하는 배열을 반환합니다. 억제된 예외가 없거나 억제가 비활성화된 경우 빈 배열이 반환됩니다.

catch 블록 에서 억제된 예외를 얻습니다 .

catch(IOException e) {
  System.out.println("Thrown exception=>" + e.getMessage());
  Throwable[] suppressedExceptions = e.getSuppressed();
  for (int i=0; i<suppressedExceptions.length; i++) {
    System.out.println("Suppressed exception=>" + suppressedExceptions[i]);
  }
}

try-with-resources를 사용하면 다음과 같은 이점이 있습니다.

  • 더 읽기 쉽고 작성하기 쉬운 코드.
  • 자동 자원 관리.
  • 코드 줄 수가 줄어듭니다.
  • try-with-resources에서 여러 리소스가 열리면 종속성 문제를 방지하기 위해 리소스를 역순으로 닫습니다.

Java 7에서 이 기능을 도입하기 전에 리소스 누수를 방지하기 위해 리소스가 닫혀 있는지 확인하기 위해 finally 블록 을 사용해야 했습니다 .

다음은 예제 1 과 유사한 프로그램입니다 . 그러나 이 프로그램에서는 리소스를 닫기 위해 finally 블록을 사용했습니다.

예 : finally 블록을 사용하여 리소스 닫기

import java.io.*;
class Main {
  public static void main(String[] args) {
    BufferedReader br = null;
    String line;
    try {
      System.out.println("Entering try block");
      br = new BufferedReader(new FileReader("test.txt"));
      while ((line = br.readLine()) != null) {
        System.out.println("Line =>"+line);
      }
    } catch (IOException e) {
      System.out.println("IOException in try block =>" + e.getMessage());
    } finally {
      System.out.println("Entering finally block");
      try {
        if (br != null) {
          br.close();
        }
      } catch (IOException e) {
        System.out.println("IOException in finally block =>"+e.getMessage());
      }
    }
  }
}

Entering try block
Line =>line from test.txt file
Entering finally block

finally 블록 의 try…catch 블록 도 보이시나요 ? 이 finally 블록 내에서 BufferedReader 인스턴스를 닫는 동안에도 IOException이 발생할 수 있으므로 이 블록도 포착되어 처리되기 때문입니다.

try -with-resources 문은 자동 리소스 관리를 수행합니다 . JVM이 자동으로 리소스를 닫으므로 리소스를 명시적으로 닫을 필요가 없습니다. 이렇게 하면 코드가 더 읽기 쉽고 작성하기 쉬워집니다.

리소스가 여러 개인 try-with-resources

리소스 를 세미콜론으로 구분하여 try-with-resources 블록 에서 여러 리소스를 잘 선언할 수 있습니다 .

try (Scanner scanner = new Scanner(new File("testRead.txt"));
    PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
    while (scanner.hasNext()) {
	writer.print(scanner.nextLine());
    }
}

Java 9 이전에는 try-with-resources 블록 내에서만 새로운 변수를 사용할 수 있었습니다.

try (Scanner scanner = new Scanner(new File("testRead.txt")); 
    PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) { 
    // omitted
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy

final Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))
try (scanner;writer) { 
    // omitted
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy

위와 같이 스캐너 변수는 명시적으로 최종 선언되므로 try-with-resources 블록 과 함께 사용할 수 있습니다 . 기록기 변수는 명시적으로 최종 변수가 아니지만 첫 번째 할당 후에 변경되지 않습니다. 따라서 writer 변수도 사용할 수 있습니다 .

즐거운 배움

Mouad Oumous Java WhatsApp 그룹에 가입하세요 .

Mouad Oumous 텔레그램 채널 가입 JOIN

그것을 따라 우리 출판물을 지원하십시오

Java에서 ModelMapper를 사용한 객체 매핑 가이드 Spring Boot 시작하기: 초보자를 위한 종합 자습서 Spring Boot Security | SSO | OAuth2 with Okta 가장 많이 묻는 Java8 스트림 기반 인터뷰 질문 — 2부 코딩: Flatten an Array in Javascript 가장 많이 묻는 Java8 스트림 기반 인터뷰 질문 — 1부