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

예외 종류
compile checked 예외
- 예외에 대한 대처 코드가 없으면 컴파일이 진행되지 않음
IOException
과SQLException
계열에 해당- 자바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 {
반드시 실행되는 문장;
}