Java Errors & Exceptions
자바에서의 오류와 예외 (Java Errors & Exceptions)
자바에서 **오류(Error)**와 **예외(Exception)**는 프로그램 실행 중에 발생하는 비정상적인 상황을 나타냅니다. 오류는 복구할 수 없는 심각한 문제를 의미하며, 예외는 프로그램에서 처리 가능하고 복구할 수 있는 비정상적인 상황을 나타냅니다. 자바는 이러한 오류와 예외를 처리하기 위한 강력한 메커니즘을 제공하며, 프로그램이 비정상적으로 종료되는 것을 방지할 수 있습니다.
1. 오류(Error)
- *
Error
*는 자바에서 심각한 문제로 간주되며, 프로그램이 정상적으로 실행될 수 없을 때 발생합니다. 이러한 문제는 주로 JVM 레벨에서 발생하며, 프로그램 코드로 복구할 수 없는 문제를 나타냅니다. 예를 들어, 메모리가 부족한 경우 **OutOfMemoryError
*가 발생합니다.
오류의 주요 유형
StackOverflowError
: 재귀 호출이 너무 깊어 스택이 넘쳤을 때 발생.OutOfMemoryError
: JVM이 더 이상 사용할 수 있는 메모리가 없을 때 발생.VirtualMachineError
: 가상 머신이 실행을 계속할 수 없을 때 발생.
public class Main {
public static void recursiveMethod() {
// StackOverflowError를 일으키는 무한 재귀 호출
recursiveMethod();
}
public static void main(String[] args) {
recursiveMethod();
}
}
설명:
- 이 코드에서는 재귀 호출이 무한히 반복되면서 **
StackOverflowError
*가 발생합니다.
2. 예외(Exception)
- *
Exception
*은 프로그램 실행 중에 발생하는 처리 가능한 오류를 의미하며, 프로그램이 비정상적으로 종료되지 않도록 예외 처리를 통해 복구할 수 있습니다. 예외는 주로 입력 오류, 파일 처리 오류, 네트워크 문제 등과 같은 상황에서 발생합니다.
예외의 주요 유형
- 검사된 예외(Checked Exception): 컴파일 타임에 처리해야 하는 예외.
- 미검사 예외(Unchecked Exception): 런타임에 발생하며, 명시적으로 처리하지 않아도 되는 예외.
2.1 검사된 예외 (Checked Exception)
검사된 예외는 컴파일러에 의해 강제로 처리해야 하는 예외입니다. 예를 들어, 파일 입출력이나 네트워크 통신과 같은 작업 중에 발생하는 예외는 처리해야 합니다.
예시: 파일 읽기에서 발생하는 IOException
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
try {
// 파일을 읽으려 시도
File file = new File("example.txt");
Scanner scanner = new Scanner(file);
} catch (FileNotFoundException e) {
// 예외 처리
System.out.println("파일을 찾을 수 없습니다: " + e.getMessage());
}
}
}
설명:
- *
FileNotFoundException
*은 검사된 예외로, 파일이 존재하지 않을 경우 발생하며 **try-catch
*로 처리해야 합니다.
2.2 미검사 예외 (Unchecked Exception)
미검사 예외는 컴파일러가 예외 처리를 강제하지 않는 예외입니다. 주로 프로그래머의 실수나 논리 오류로 인해 발생하며,
대표적으로 NullPointerException
,
ArrayIndexOutOfBoundsException
등이 있습니다.
예시: 배열 인덱스 초과에서 발생하는 ArrayIndexOutOfBoundsException
public class Main {
public static void main(String[] args) {
int[] numbers = {1, 2, 3};
// 배열 범위를 초과하는 인덱스에 접근
System.out.println(numbers[5]); // ArrayIndexOutOfBoundsException 발생
}
}
설명:
- 이 코드에서는 배열의 범위를 초과하여 접근하려고 시도하면서 **
ArrayIndexOutOfBoundsException
*이 발생합니다. 이는 미검사 예외입니다.
3. 예외 처리 (Exception Handling)
자바에서 예외를 처리하는 기본 메커니즘은 try-catch-finally
블록을 사용하는 것입니다. 예외가 발생할 수 있는 코드를
try
블록에 넣고, 예외가 발생하면 catch
블록이 실행됩니다.
finally
블록은 예외 발생 여부에 상관없이 항상 실행됩니다.
3.1 try-catch
블록
public class Main {
public static void main(String[] args) {
try {
// 예외 발생 가능 코드
int result = 10 / 0; // ArithmeticException 발생
} catch (ArithmeticException e) {
// 예외 처리
System.out.println("0으로 나눌 수 없습니다: " + e.getMessage());
}
}
}
설명:
try
블록에서 **ArithmeticException
*이 발생하면,catch
블록이 이를 처리합니다.
3.2 finally
블록
finally
블록은 예외가 발생하더라도 항상 실행되는 코드 블록입니다. 주로 파일 닫기, 자원 해제 등의 작업을 수행하는 데
사용됩니다.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = null;
try {
// 파일 읽기 시도
File file = new File("example.txt");
scanner = new Scanner(file);
} catch (FileNotFoundException e) {
System.out.println("파일을 찾을 수 없습니다.");
} finally {
// 자원 해제
if (scanner != null) {
scanner.close();
System.out.println("Scanner를 닫았습니다.");
}
}
}
}
설명:
finally
블록에서scanner
를 닫는 작업은 예외 발생 여부와 관계없이 항상 실행됩니다.
4. throw
와 throws
키워드
4.1 throw
: 예외 강제로 발생시키기
throw
키워드는 예외를 강제로 발생시킬 때 사용됩니다. 이는 예외를 직접 정의하고 발생시키는
방법입니다.
public class Main {
public static void main(String[] args) {
try {
// 예외를 강제로 발생
throw new ArithmeticException("강제로 발생시킨 예외");
} catch (ArithmeticException e) {
System.out.println(e.getMessage());
}
}
}
설명:
- *
throw
*를 사용하여ArithmeticException
을 강제로 발생시킵니다.
4.2 throws
: 메서드에서 예외 던지기
throws
키워드는 메서드에서 예외가 발생할 수 있음을 선언하고, 메서드를 호출한 곳에서 처리하도록 위임합니다.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
readFile();
}
public static void readFile() throws FileNotFoundException {
File file = new File("example.txt");
Scanner scanner = new Scanner(file); // 예외를 호출한 메서드로 던짐
}
}
설명:
throws
키워드를 사용하여 메서드가 처리하지 않고 예외를 호출한 메서드로 넘깁니다.
5. 사용자 정의 예외 (Custom Exception)
자바에서는 사용자가 직접 예외 클래스를 정의하여 특정한 상황에 맞는 예외를 만들 수 있습니다. 사용자 정의 예외는
Exception
클래스를 상속하여 구현합니다.
사용자 정의 예외 예시
// 사용자 정의 예외 클래스
class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message);
}
}
public class Main {
public static void main(String[] args) {
try {
checkAge(15); // 예외 발생
} catch (InvalidAgeException e) {
System.out.println(e.getMessage());
}
}
// 나이를 확인하는 메서드
public static void checkAge(int age) throws InvalidAgeException {
if (age < 18) {
throw new InvalidAgeException("나이가 18세 미만입니다.");
}
}
}
설명:
- *
InvalidAgeException
*은 사용자 정의 예외로, 나이가 18세 미만일 때 예외를 발생시킵니다.
6. 예외 계층 구조
자바에서 예외는 Throwable
클래
스를 기반으로 하며, 그 아래에 **Error
**와 **Exception
**이 있습니다.
Throwable
: 모든 예외와 오류의 상위 클래스.Error
: JVM에서 발생하는 심각한 오류.Exception
: 복구 가능한 예외.RuntimeException
: 런타임 예외(미검사 예외).
Throwable
│
├── Error
│ └── (예: OutOfMemoryError, StackOverflowError)
│
└── Exception
├── IOException (Checked Exception)
└── RuntimeException (Unchecked Exception)
├── NullPointerException
└── ArithmeticException
요약
- 오류(Error): JVM에서 발생하며 복구 불가능한 문제, 예를 들어
OutOfMemoryError
. - 예외(Exception): 복구 가능한 문제로, **검사된 예외(Checked)**와 **미검사 예외(Unchecked)**로 나뉨.
try-catch-finally
: 예외 처리 메커니즘.throw
: 예외를 강제로 발생.throws
: 메서드에서 발생할 수 있는 예외를 선언하고 호출자에게 전달.- 사용자 정의 예외: 필요에 따라 새로운 예외 클래스를 정의하여 특정 상황을 처리.
자바의 예외 처리 메커니즘을 이해하고 사용함으로써, 예외 발생 시 프로그램이 비정상 종료되지 않고 적절하게 복구할 수 있습니다.