Language/JAVA

[JAVA] 예외(Exception) 처리

gangintheremark 2023. 7. 24. 15:41
728x90

예외(Exception)

프로그램 실행 중에 발생되는 의도하지 않은 문제 발생을 의미한다. 예외가 발생되면 프로그램은 비정상종료된다. 예외처리란 예외 발생 시 비정상 종료되는 프로그램을 정상종료로 처리하는 작업을 의미한다. 여기서 예외가 발생된 코드를 수정하는 것은 예외처리가 아니다. 예외처리를 담당하는 예외클래스를 활용한다.

예외 클래스 계층구조

 


예외 종류

compile checked 예외

  • 예외에 대한 대처 코드가 없으면 컴파일이 진행되지 않음
  • IOExceptionSQLException 계열에 해당
  • 자바I/O 및 데이터베이스 관련 작업을 수행하는 메서드를 사용하기 위해서 반드시 예외처리를 해야 한다.

compile unchecked 예외

  • 예외에 대한 대처 코드가 없더라도 컴파일은 진행됨
  • 컴파일시 예외처리 여부를 컴파일러가 체크x 👉 왜? 개발자가 조건문 코드를 추가 작성하면 발생되지 않을 예외이기 때문
  • RuntimeException 계열에 해당 - NullPointerException ArithmeticException

예외 처리 방법

try-catch 문

예외가 발생된 곳에서 예외를 처리

try {
 문장1;
 문장2;
} catch(예외클래스 e) {
 예외처리코드;
}
class Test {
    public void func() {
        try {
            // ArithmeticException 발생 가능한 코드
            int num = 0;
            int result = 10 / num; // 예외 발생 ==> 비정상 종료
            System.out.println("결과값 : " + result);
        } catch (ArithmeticException e) { // ==> try-catch문 사용시 정상종료 됨.
            System.out.println("Error: 0으로 나누어 발생");
        }
    }
}

 

throws

예외가 발생된 곳이 아닌 호출한 메서드로 예외처리를 위임하는 방식

 

💡 throws문을 이용해서 예외 처리하는 대표적인 경우

  • 사용자가 지정한 특정조건에 위배될 경우 예외를 명시적으로 발생시켜 처리
  • 발생된 시스템 예외클래스 대신 사용자가 만든 예외클래스로 처리하기 위함
public void method() throws 예외클래스 {}
class Test {
    public void b() throws NullPointerException {
        System.out.println("Test.a");

        // NullPointerException 발생 가능한 코드
        String n = null;
        System.out.println(n.length()); // 예외 발생
    }
}

public class Main {
    public static void main(String[] args) {
        Test t = new Test();

        try {
            t.a();
        } catch (NullPointerException e) {
            System.out.println("errer: 객체 생성 필요");
        } catch (Exception e) {
            System.out.println("error 발생");
        }
    }
}

 

throw 명시적 예외 강제 발생

특정 조건을 위반했을 경우에 명시적으로 예외를 발생시키는 방법

if(조건) { 
 throw new 예외클래스(msg);
 }
public void method(int num) throws Exception {
     if (num < 0) {
         throw new Exception("음수값 에러 발생");
     }
}

 


다중 catch 문

try 블록 내에서 실행되는 문장이 여러 개 있는 경우에는 발생되는 예외도 달라질 수 있다. 주의할 점은 반드시 계층구조가 낮은 예외클래스부터 catch 해야 된다. 상위 타입의 예외가 먼저 선언되는 경우 뒤에 등장하는 catch 블록은 동작할 기회가 없다.

try {
    문장1;
    문장2;
} catch (예외클래스명 e) {
    예외처리코드;
} catch (예외클래스명 e) {
    예외처리코드;
} catch (Exception e) { // 예외클래스 중 최상위 객체 
    예외처리코드;
}

발생하는 예외들을 Exception e 를 통해 하나로 처리할 수 있지만 가급적 예외 상황 별로 처리하는 것을 권장한다. 하지만 심각하지 않은 예외를 굳이 세분화 해서 처리하는 것도 낭비이므로 | 를 이용하여 하나의 catch 구문에 상속관계가 없는 여러 개의 exception을 처리한다.

    public void exceptionHandling() {
        try {
        Class.forName("abc.Def");
        new FileInputStream("Hello.java");
        DriverManager.getConnection("Hello");
        } catch (ClassNotFoundException  | FileNotFoundException e) {
            System.out.println(e.getMessage());
        } catch (SQLException e) {
            System.out.println(e.getMessage());            
        }
    }

 

finally 문

예외 발생 여부와 상관없이 무조건 실행되어야 하는 문장을 지정한다. 중간에 return을 만나는 경우도 finally 블록을 먼저 수행 후 리턴을 실행한다. 주요 목적은 try 블록에서 사용한 리소스를 반납하기 위해 사용하며 생성한 시스템 자원을 반납하지 않으면 resource leak 발생이 가능하다. 반드시 사용한 자원은 finally 블록에서 close 처리를 해야한다.

try {
    문장1;
    문장2;
} catch (예외클래스명 e) {
    예외처리코드;
}  finally {
    반드시 실행되는 문장;
}
728x90