Error는 JVM 수준에서 발생하는 심각한 문제로, 애플리케이션이 복구할 수 없는 상황이다.
OutOfMemoryError: JVM 힙 메모리 고갈StackOverflowError: 스택 메모리 초과 (무한 재귀 등)NoClassDefFoundError: 클래스 로딩 실패Exception은 애플리케이션 로직에서 발생할 수 있는 문제로, 적절히 처리하면 복구 가능한 상황이다.
// 1. IOException - 파일 입출력 시 발생
public String readFile(String path) throws IOException { // ✅ throws 선언 필수
BufferedReader reader = new BufferedReader(new FileReader(path));
try {
return reader.readLine();
} finally {
reader.close();
}
}
// 호출하는 쪽에서 반드시 처리해야 함
public void caller() {
try {
String content = readFile("/path/to/file.txt");
} catch (IOException e) { // ✅ 반드시 catch 또는 throws
// 파일이 없거나, 권한이 없거나, 디스크 문제 등
// 대체 파일 사용, 재시도, 사용자에게 알림 등 복구 시도
logger.error("Failed to read file", e);
}
}
// 2. SQLException - 데이터베이스 작업 시 발생
public User findUser(Long id) throws SQLException {
Connection conn = dataSource.getConnection();
try {
PreparedStatement stmt = conn.prepareStatement(
"SELECT * FROM users WHERE id = ?"
);
stmt.setLong(1, id);
ResultSet rs = stmt.executeQuery();
// ... 결과 처리
} finally {
conn.close();
}
}
// 3. ClassNotFoundException - 동적 클래스 로딩 시 발생
public Object createInstance(String className) throws ClassNotFoundException {
Class<?> clazz = Class.forName(className); // 체크드 예외 발생 가능
// 설정 파일에 명시된 클래스가 classpath에 없을 수 있음
}
// 1. NullPointerException - 가장 흔한 언체크드 예외
public void processUser(User user) {
// user가 null이면 NPE 발생
String name = user.getName(); // ❌ 프로그래밍 오류
// 올바른 방법
if (user == null) {
throw new IllegalArgumentException("User cannot be null");
}
String name = user.getName(); // ✅
}
// 2. IllegalArgumentException - 잘못된 인자
public void setAge(int age) {
if (age < 0 || age > 150) {
throw new IllegalArgumentException(
"Invalid age: " + age + ". Must be between 0 and 150"
);
}
this.age = age;
}
// 3. IllegalStateException - 잘못된 상태에서 메서드 호출
public class OrderProcessor {
private Order order;
private boolean processed = false;
public void process() {
if (processed) {
throw new IllegalStateException("Order already processed");
}
// 주문 처리
processed = true;
}
}
// 4. ArrayIndexOutOfBoundsException - 배열 인덱스 범위 초과
public int getElement(int[] array, int index) {
// index가 범위를 벗어나면 발생
return array[index]; // 프로그래머가 검증해야 함
}
// 5. NumberFormatException - 문자열을 숫자로 변환 실패
public int parseUserInput(String input) {
try {
return Integer.parseInt(input);
} catch (NumberFormatException e) {
// 사용자 입력이 숫자가 아님
return 0; // 기본값 반환
}
}
// 방법 1: 직접 처리
public void method1() {
try {
Files.readAllLines(Paths.get("config.txt"));
} catch (IOException e) {
// 복구 로직: 기본 설정 사용
useDefaultConfiguration();
}
}
// 방법 2: 호출자에게 전파 (throws)
public void method2() throws IOException {
Files.readAllLines(Paths.get("config.txt"));
// 호출자가 처리하도록 위임
}
// 방법 3: 비즈니스 예외로 래핑
public void method3() {
try {
Files.readAllLines(Paths.get("config.txt"));
} catch (IOException e) {
throw new ConfigurationException("Failed to load config", e);
}
}
// 보통 catch하지 않음 - 프로그램 버그이므로 수정해야 함
public void processOrder(Order order) {
// order가 null이면 NPE 발생 → 버그 수정 필요
order.validate();
}
// 하지만 외부 입력 검증 시에는 catch할 수 있음
public void handleUserInput(String input) {
try {
int value = Integer.parseInt(input);
processValue(value);
} catch (NumberFormatException e) {
// 사용자에게 메시지
showError("Please enter a valid number");
}
}