예외란 프로그램 실행 중 발생하는 예기치 못한 상황을 의미한다. 만약 이러한 예외를 처리하지 않으면 프로그램이 비정상적으로 종료되거나, 예기치 않은 결과를 초래할 수 있다. Java에서 예외 처리(Exception Handling)는 코드 작성자가 예기치 않게 발생하는 에러들에 대응할 수 있도록 사전에 방지하는 것으로, 안정적이고 신뢰성 있는 소프트웨어를 개발하기 위해 반드시 알아야 할 중요한 기술이다. 그렇기에 예외 처리의 개념과 실제 사용법을 잘 이해하고 사용하는 게 중요하다.
1. 예외 처리(Exception Handling)가 중요한 이유
에러 발생 요인으로는 내부적인 요인과 외부적인 요인이 있다. 외부적 요인에는 사용자의 입력 에러, 하드웨어 문제, 네트워크 연결 에러 등이 있으며, 내부적인 요인으로는 개발자의 코드 작성에 있다.
- 비정상적인 종료 방지: 예외 발생 시에도 프로그램의 흐름을 유지하여 안정성을 높인다.
- 문제 해결 용이성: 발생한 예외의 원인을 파악하고 이를 적절히 처리하여 디버깅 시간을 단축할 수 있다.
- 사용자 경험 개선: 오류 메시지를 사용자 친화적으로 제공함으로써 사용자가 원인을 이해하고 대응할 수 있도록 돕는다.
2. 에러(Error)와 예외(Exception)의 차이
Java에서 에러(Error)와 예외(Exception)는 모두 Throwable 클래스를 상속하지만, 성격과 처리 방식에서 차이가 있다.
1) 에러 (Error)
시스템 레벨에서 발생하는 치명적인 문제로, 애플리케이션 코드로 해결할 수 없다.
- 주로 JVM 내부 문제로 발생하며 복구 불가능하다.
- JVM 메모리 부족(OutOfMemoryError), 스택 오버플로우(StackOverflowError: 재귀 호출의 깊이가 한계를 초과) 등으로 인해 발생한다.
public class ErrorExample {
public static void main(String[] args) {
recursiveMethod();
}
public static void recursiveMethod() {
recursiveMethod(); // 무한 재귀 호출
}
}
실행결과) StackOverflowError는 무한 재귀 호출로 인해 발생하며, 이를 코드로 복구할 수 없다.
Exception in thread "main" java.lang.StackOverflowError
2) 예외 (Exception)
주로 개발자의 잘못된 사용으로 인해 발생하는 것으로, 개발자의 코드로 복구 가능한 문제이다.
- 잘못된 입력, 파일 접근 실패, 네트워크 연결 실패 등으로 인해 발생하며, 적절한 예외 처리 코드를 통해 복구 가능하다.
- IOException(파일 입출력 중 문제 발생), NullPointException(null 객체 참조할 때 발생) 등이 예이다.
public class ExceptionExample {
public static void main(String[] args) {
String value = null;
System.out.println(value.length()); // NullPointerException 발생
}
}
Exception in thread "main" java.lang.NullPointerException
자바에서 예외가 발생하면 예외 클래스로부터 객체를 생성하여 해당 인스턴스를 통해 예외처리를 한다. 자바의 모든 에러와 예외 클래스는 Throwable 클래스로부터 확장되며, 모든 예외(Exception)의 상위 클래스는 Exception 클래스이다. Exception 클래스는 크게 실행 예외 클래스(Runtime Exception)와 일반 예외 클래스(Other Exception)로 구분된다.
3. 예외의 종류
자바에서 예외가 발생하면 예외 클래스로부터 객체를 생성하여 해당 인스턴스를 통해 예외처리를 한다. 자바의 모든 에러와 예외 클래스는 Throwable 클래스로부터 확장되며, 모든 예외(Exception)의 상위 클래스는 Exception 클래스이다. Exception 클래스는 크게 실행 예외 클래스(Runtime Exception 또는 UnChecked) 예외와 일반 예외 클래스(Other Exception 또는 Checked 예외)로 구분된다.
1) 일반 예외 클래스(Other Exception)
런타임 시 발생하는 예외를 제외한 모든 Exception 클래스와 하위 클래스들을 말한다. 컴파일러가 코드 실행 전에 예외 처리 코드 여부를 검사하기 때문에 Checked 예외라고도 부른다. 컴파일 타임에 반드시 처리해야 하는 예외이다.
- 발생 가능성이 높은 예외를 컴파일러가 강제적으로 검사한다.
- 예외 처리 코드가 없으면 컴파일되지 않는다.
- FileNotFoundException(파일 존재하지 않을 때 발생), SQLException(데이터베이스 작업 중 문제 발생) 등이 예이다.
import java.io.*;
public class CheckedExceptionExample {
public static void main(String[] args) {
try {
FileReader reader = new FileReader("exceptionTest.txt");
} catch (FileNotFoundException e) {
System.out.println("파일을 찾을 수 없습니다: " + e.getMessage());
}finally{
System.out.println("파일 읽기 작업 완료");
}
}
}
/*
실행 결과:
파일을 찾을 수 없습니다: exceptionTest.txt (No such file or directory)
*/
2) 실행 예외 클래스(Runtime Exception)
런타임에 발생하는 런타임 에러로, Runtime Exception클래스와 하위 클래스들을 말한다. 컴파일 시 잡지 못하고 실행 시에 프로그램이 종료되며, 컴파일러가 처리 여부를 검사하지 않기 때문에 Unchecked 예외라고도 부른다.
- 주로 개발자의 실수로 인해 발생하며, 발생 시 프로그램이 비정상 종료될 수 있다.
- ArithmeticException(0으로 나누는 연산), ArrayIndexOutOfBoundsException(배열 범위 초과한 인덱스 접근), NullPointException(null인 참조 변수 사용 시 발생)
public class UncheckedExceptionExample {
public static void main(String[] args) {
int[] numbers = {1, 2, 3};
System.out.println(numbers[3]); // ArrayIndexOutOfBoundsException 발생
}
}
/*
실행 결과:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
*/
4. 예외 처리 구문
Java는 try-catch-finally 블록으로 예외를 처리한다.
try{
// 예외 발생 가능성이 있는 코드
}catch (ExceptionType1 e1) {
// ExceptionType1 처리
} catch (ExceptionType2 e2) {
// ExceptionType2 처리
} finally {
// 예외 발생 여부와 상관없이 항상 실행
}
try문에서는 예외가 발생할 수 있는 코드를 작성하고, catch문에서는 try문에서 발생한 예외를 처리한다. finally 구문은 예외와 상관없이 무조건 실행된다. try문에서 작성한 코드가 예외 없이 정상적으로 동작하면 catch 블록은 실행되지 않고, 예외 처리를 종료하거나 finally 블록이 실행된다.
import java.io.*;
public class TryCatchExample {
public static void main(String[] args) {
try {
FileReader file = new FileReader("example.txt");
} catch (FileNotFoundException e) {
System.out.println("파일이 존재하지 않습니다.");
} finally {
System.out.println("예외 처리 완료.");
}
}
}
/*
실행 결과:
파일이 존재하지 않습니다.
예외 처리 완료.
*/
5. 예외 처리 방식
1) 예외 전가 (throws)
throws 키워드를 사용해 메서드에서 발생할 수 있는 예외들을 쉼표로 구분하여 나열하는 것으로 작성하며, 호출자에게 전가할 수 있다. throws를 사용하면 자바 JVM이 최종적으로 예외의 내용을 콘솔에 출력하여 예외 처리를 수행한다.
예외를 던지거나 처리하는 기준은 예외를 발생시킨 메서드가 해당 예외를 처리할 수 있는지를 기준으로 한다. 처리할 수 있으면 try-catch문으로 처리하고, 없으면 throws를 사용한다.
import java.io.*;
public class ThrowsExample {
public static void main(String[] args) throws IOException {
readFile();
}
public static void readFile() throws IOException {
FileReader reader = new FileReader("example.txt");
}
}
/*
실행 결과:
Exception in thread "main" java.io.FileNotFoundException: example.txt (No such file or directory)
*/
2) 예외 발생 (throw)
throw 키워드를 사용해 예외를 의도적으로 발생시켜 예기치 않게 발생할 수 있는 에러에 대응할 수 있도록 사전에 코드를 작성하여 예외 처리를 할 수 있다.
public class ThrowExample {
public static void main(String[] args) {
checkValue(-1);
}
public static void checkValue(int value) {
if (value < 0) {
throw new IllegalArgumentException("값은 음수일 수 없습니다.");
}
}
}
/*
실행 결과:
Exception in thread "main" java.lang.IllegalArgumentException: 값은 음수일 수 없습니다.
*/
6. 커스텀 예외
Java에서 제공하는 기본 예외 클래스로 처리할 수 없는 특정 상황을 위해 사용자 정의 예외 클래스를 생성할 수 있다. 예외를 잘게 나눌 지 커스텀 예외 클래스를 만들지, 자바 기본 예외 클래스를 사용할 지는 상황에 따라 다르다.
// 자바 기본 예외 클래스 사용
public void checkArgument(Object arg) {
if (arg == null) {
throw new IllegalArgumentException("Argument cannot be null");
}
}
// 커스텀 예외 클래스 사용
public class CustomException extends Exception {
public CustomException(String message) {
super(message);
}
}
public class CustomExceptionExample {
public static void main(String[] args) {
try {
validateAge(16);
} catch (CustomException e) {
System.out.println("예외 발생: " + e.getMessage());
}
}
public static void validateAge(int age) throws CustomException {
if (age < 18) {
throw new CustomException("나이는 18세 이상이어야 한다.");
}
}
}
[출처: https://f-lab.kr/insight/java-exception-handling-20240625, https://ittrue.tistory.com/140]
'Programming Language > Java' 카테고리의 다른 글
[Java/개념] 정적 팩토리 메서드 (0) | 2024.12.10 |
---|---|
[Java/개념] Optional<T> 클래스 (0) | 2024.12.05 |
[Java/개념] Math, Random (0) | 2024.12.05 |
[Java/개념] API)String, StringTokenizer, StringBuffer, StringBuilder (0) | 2024.12.05 |
[Java/개념] API 도큐먼트, java.lang, java.util, java.lang.Object, java.util.Object (0) | 2024.12.05 |