상세 컨텐츠

본문 제목

[Java] Exception, try-catch-finally, try-with-resources

😎 지식/자바☕

by :Eundms 2023. 12. 24. 12:00

본문

Exception?

프로그램 실행 중에 발생하여 프로그램 명령의 정상적인 흐름을 방해하는 이벤트

 
- 메소드 내에서 오류가 발생하면 메소드는 객체를 생성하고 이를 런타임 시스템에 전달한다
===> 예외 개체에는 오류가 발생한 당시의 프로그램 상태, 유형을 포함한 오류에 대한 정보를 담고 있다

exception handler를 찾지 못한 채 호출 스택의 모든 메서드를 검색한 경우 런타임 시스템이 종료된다.

 
try : exception에 대한 handler(catch)를 제공해야 한다
throws : exception을 던질 수 있는 메서드라는 것을 명시하는 구문

던질 수 있는 클래스와 서브 클래스

Throwable 클래스

 

예외의 장점

1. 오류 처리 코드를 일반 코드와 분리할 수 있다
2. 호출 스택 위로 오류를 전파할 수 있다
3. 오류 유형을 그룹화하고 구별할 수 있다


 

3가지 종류의 예외

1. Checked Exception

잘 작성된 애플리케이션이 예상하고 복구해야 하는 예외
Error, RuntimeException과 그 서브 클래스를 제외한 모든 Exception
ex) java.io.FileNotFoundException

2. Error

애플리케이션 외부에 있는 예외적인 조건, 애플리케이션이 예상하거나 복구할 수 없는 예외
오류는 Catch 또는 Specific Requirement(획득 또는 지정 요구사항)의 적용을 받지 않음
Error와 그 하위 클래스
ex) java.io.IOError

3. Runtime Exception

애플리케이션 내부에 있는 예외적인 조건, 애플리케이션이 예상하거나 복구할 수 없음
논리 오류나 API의 부적절한 사용과 같은 프로그래밍 버그
예외 발생을 야기한 버그를 제거해야 함
ex) NullPointerException


 

try-catch-finally와 try-with-resources (Java SE7)

try-with-resources 문은 Closeable과 같은 리소스(ex Stream)를 사용하는 상황에 적합함
// Note: This class will not compile yet.
import java.io.*;
import java.util.List;
import java.util.ArrayList;

public class ListOfNumbers {

    private List<Integer> list;
    private static final int SIZE = 10;

    public ListOfNumbers () {
        list = new ArrayList<Integer>(SIZE);
        for (int i = 0; i < SIZE; i++) {
            list.add(new Integer(i));
        }
    }

    public void writeList() {
	// The FileWriter constructor throws IOException, which must be caught.
        PrintWriter out = new PrintWriter(new FileWriter("OutFile.txt"));

        for (int i = 0; i < SIZE; i++) {
            // The get(int) method throws IndexOutOfBoundsException, which must be caught.
            out.println("Value at: " + i + " = " + list.get(i));
        }
        out.close();
    }
}

IOException 과 IndexOutOfBoundsException이 처리되어야 한다
 

ex) 위의 코드를 Exception 처리 하는 방법을 알아보자

1. 예외를 발생시킬 수 있는 (1)각 코드 줄을 try 블록 내에 배치하고 (2) 각각에 대해 별도의 exception handler를 제공한다

private List<Integer> list;
private static final int SIZE = 10;

public void writeList() {
    PrintWriter out = null;
    try { //하나의 try block
        System.out.println("Entered try statement");
        FileWriter f = new FileWriter("OutFile.txt"); // IOException
        out = new PrintWriter(f);
        for (int i = 0; i < SIZE; i++) {
            out.println("Value at: " + i + " = " + list.get(i)); // IndexOutOfBoundsException
        }
    }
    catch and finally blocks  . . .
}

 

try {

} catch (IndexOutOfBoundsException e) {
    System.err.println("IndexOutOfBoundsException: " + e.getMessage());
} catch (IOException e) {
    System.err.println("Caught IOException: " + e.getMessage());
}

 

Java SE 7 이상에서는 단일 catch 블록이 두 가지 이상의 예외 유형을 처리할 수 있음
catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}

 

finally 블록

예외가 발생해도 블록이 실행된다. 그래서 실수로 return, continue 에 의해 정리 코드를 우회하는 것을 방지할 수 있다.
위의 예제에서 3가지 방법 중 하나로 finally 블록이 종료될 수 있기 때문에 다소 복잡하다.

  1. FileWriter 구문이 실패하고 IOException이 발생한다
  2. list.get(i) 구문이 실패하고 IndexOutOfBoundsException 이 발생한다
  3. 모든 것이 성공되고, try block이 정상적으로 종료된다

이렇게 3가지 방법 중 하나로 실행될 수 있기 때문에 다음과 같은 코드가 작성되어야 한다

finally {
    if (out != null) { 
        System.out.println("Closing PrintWriter");
        out.close(); 
    } else { 
        System.out.println("PrintWriter not open");
    } 
    if (f != null) {
	    System.out.println("Closing FileWriter");
	    f.close();
	}	
}

 

try - with - resources 구문을 finally block 대신에 사용해라

try-with-resources 구문은 더 이상 필요하지 않은 시스템 리소스를 자동으로 release한다

public void writeList() throws IOException {
    try (FileWriter f = new FileWriter("OutFile.txt");
         PrintWriter out = new PrintWriter(f)) {
        for (int i = 0; i < SIZE; i++) {
            out.println("Value at: " + i + " = " + list.get(i));
        }
    }
}

try-with-resources ?

 구문의 끝에서 resource가 닫히는 것이 보장된다
java.lang.AutoCloseable이나 java.io.Closeable을 구현하는 Object는 resource로 사용될 수 있다
 
Java SE 7이후에는 FileReader, BufferedReader 가 java.lang.AutoCloseable을 구현한다. 
그러므로, try-with-resources에 사용할 수 있고, try문이 정상적으로 완료되었는지 여부에 관계없이 resources는 닫히게 된다.

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

Java SE 7 이전에는 finally 블록에서 리소스를 닫도록 처리했다. 하지만, 리소스 누수가 있을 수 있다. 리소스의 close 메서드를 호출해서 운영체제에게 해제를 요청해야 한다. 하지만, GC가 리소스를 회수하기 전에 이 작업을 수행하지 못하면 리소스를 해제하는 데 필요한 정보가 손실된다.
 
- 리소스의 메서드는 생성 순서와 반대 순서로 호출된다.

public static void writeToFileZipFileContents(String zipFileName,
                                           String outputFileName)
                                           throws java.io.IOException {

    java.nio.charset.Charset charset =
         java.nio.charset.StandardCharsets.US_ASCII;
    java.nio.file.Path outputFilePath =
         java.nio.file.Paths.get(outputFileName);

    // Open zip file and create output file with 
    // try-with-resources statement

    try (
        java.util.zip.ZipFile zf =
             new java.util.zip.ZipFile(zipFileName);
        java.io.BufferedWriter writer = 
            java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
    ) {
        // Enumerate each entry
        for (java.util.Enumeration entries =
                                zf.entries(); entries.hasMoreElements();) {
            // Get the entry name and write it to the output file
            String newLine = System.getProperty("line.separator");
            String zipEntryName =
                 ((java.util.zip.ZipEntry)entries.nextElement()).getName() +
                 newLine;
            writer.write(zipEntryName, 0, zipEntryName.length());
        }
    }
}

 

 
 


https://docs.oracle.com/javase/tutorial/essential/exceptions/index.html

 

Lesson: Exceptions (The Java™ Tutorials > Essential Java Classes)

The Java Tutorials have been written for JDK 8. Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available. See Java Language Changes for a summary of updated

docs.oracle.com

 

'😎 지식 > 자바☕' 카테고리의 다른 글

[Java] Enum  (0) 2024.03.11
[Java] Java 메모리 구조, Reflection,  (0) 2024.01.06
2. 생성자에 매개변수가 많다면 빌더를 고려해라  (0) 2023.10.17

관련글 더보기

댓글 영역