Java

[Java] 예외 처리

junga 2022. 9. 15. 22:38

오류(error)와 예외(exception)


오류

  • 오류는 시스템이 종료되어야 할 수준의 상황과 같이 수습할 수 없는 심각한 문제를 의미합니다.
  • 개발자가 미리 예측하여 방지할 수 없습니다.


예외

  • 예외는 개발자가 구현한 로직에서 발생한 실수나 사용자의 영향에 의해 발생합니다.
  • 오류와 달리 개발자가 미리 예측하여 방지할 수 있기에 상황에 맞는 예외처리(Exception Handle)를 해야합니다.


예외의 구분


RuntimeException을 상속하지 않는 클래스는 Checked Exception로 분류할 수 있고,
RuntimeException을 상속하는 클래스는 Unchecked Exception으로 분류할 수 있다.



CheckedException

  • 체크 예외는 RuntimeException의 하위 클래스가 아니면서 Exception 클래스의 하위 클래스들입니다.
  • 반드시 에러 처리를 해야하는 특징(try/catch or throw)을 가지고 있습니다.
  • 스프링 프레임워크에서 CheckedException은 트랜젝션 처리 시에 예외가 발생해도 롤백하지 않는다.

ex)
존재하지 않는 파일의 이름을 입력(FileNotFoundException)
실수로 클래스의 이름을 잘못 적음(ClassNotFoundException)



UnCheckedException

  • RuntimeException의 하위 클래스들을 의미합니다.
  • 체크 예외와는 달리 에러 처리를 강제하지 않습니다.
  • 말 그대로 실행 중에(runtime) 발생할 수 있는 예외를 의미합니다.
  • 스프링 프레임워크에서 UncheckedException은 트랜젝션 처리시에 예외가 발생한 경우 롤백을 수행한다.

ex)
배열의 범위를 벗어난(ArrayIndexOutOfBoundsException)
값이 null이 참조변수를 참조(NullPointerException)



예외 처리(exception handling)

try - catch - finally

try {
    예외를 처리하길 원하는 실행 코드;
} catch (e1) {
    e1 예외가 발생할 경우에 실행될 코드;
} catch (e2) {
    e2 예외가 발생할 경우에 실행될 코드;
}
...
finally {
    예외 발생 여부와 상관없이 무조건 실행될 코드;
}
  1. try: 기본적으로 맨 먼저 실행되는 코드로, 여기서 발생한 예외는 catch 블록에서 처리된다.
  2. catch: try 블록에서 발생한 예외 코드나 예외 객체를 인수로 전달받아 그 처리를 담당한다.
  3. finally: try 블록에서 예외가 발생하건 안 하건 맨 마지막에 무조건 실행된다.

(try / catch) 또는 (try / finally) 조합으로도 사용이 가능하다.



throw

  • throw: 에러를 고의로 발생시킬 때 사용한다.
import java.io.IOException;

public class Main {
    public static void main(String[] args){
        try {
            throw new IOException(); // 예외 발생시키기
        }catch(IOException e) {
            e.printStackTrace(); // 예외 상황을 출력해주는 메서드
        }
        System.out.println("예외 처리 완료");
    }
}
// java.io.IOException
//     at junga2.Main.main(Main.java:9)
// 예외 처리 완료


throws

  • throws: 자신을 호출한 상위 메소드로 에러를 던지는 역할을 한다.
import java.io.IOException;

public class Main {
    public static void main(String[] args){
        TException te = new TException();
        try {
            te.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("예외 처리 완료");
    }
}

class TException{
    public void read() throws IOException  {
        throw new IOException(); // 에러 발생
    }
}
// java.io.IOException
//     at junga2.TException.read(Main.java:40)
//     at junga2.Main.main(Main.java:30)
// 예외 처리 완료

throws를 사용하면 예외가 발생되는 메소드를 호출하는 곳에서 예외 처리를 해준다.



사용자 정의 예외

// 사용자 정의 예외 클래스 선언
class MyException extends Exception {
    public MyException() {}
    public MyException(String message) {super(message);}
}

public class Main {
    public static void main(String[] args) {
        try {
            throw new MyException("메세지"); // 예외 발생 시키기
        } catch (MyException e) {
            System.out.println(e.getMessage());
            System.out.println("예외 처리 완료");
        }
    }
}

// 메세지
// 예외 처리 완료


try - with - resources


  • Java SE 7 부터는 사용한 자원을 자동으로 해제해 주는 try - with - resources를 사용할 수 있다.
  • try에 괄호를 추가하여 파일을 열거나 자원을 할당하는 명령문을 명시하면,
  • 해당 try 블록이 끝나자마자 자동으로 파일을 닫거나, 할당된 자원을 해제해 준다.
try (파일을열거나자원을할당하는명령문) {
     ...
}

파일에서 문자열을 한 줄 읽어오는 예제다.
아래 두 코드는 내용이 똑같다.

// try - finally 사용
static String readFile(String filePath) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(filePath));
    try {
        return br.readLine();
    } finally {
        if (br != null)
            br.close();
    }
}
// try - with - resources 사용 => 자동으로 파일을 닫아준다.
static String readFile(String filePath) throws IOException {
    try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
        return br.readLine();
    }
}

'Java' 카테고리의 다른 글

[Java] 람다식과 함수형 인터페이스  (0) 2022.09.17
[Java] 제네릭 generic  (0) 2022.09.17
[Java] 입출력 스트림  (0) 2022.09.15
[Java] 내부 클래스와 익명 클래스  (0) 2022.09.14
[Java] static & final & static final 차이  (0) 2022.09.12