ex) OutOfMemoryError, ThreadDeath, StackOverflowError 등

상속 관계가 이렇게 되어 있는 이유는 Exception이나 Error의 성격은 다르지만, 모두 동일한 이름의 메소드를 사용하여 처리할 수 있도록 하기 위함
컴파일러가 해당 예외를 확인하고 처리 여부를 강제하는 예외

| Checked Exception 종류 | |
|---|---|
| IOException | 입출력 작업 중에 발생하는 예외 (파일을 읽거나 쓸 때 발생) |
| SQLException | 데이터베이스 작업 중에 발생하는 예외 (데이터베이스 연결, 쿼리 실행, 트랜잭션 등) |
컴파일러가 해당 예외를 확인하지 않고 예외 처리를 강제하지 않는 예외
RuntimeException을 상속한 클래스
| Unchecked Exception 종류 | |
|---|---|
| NullPointerException | null 값을 갖는 참조 변수로 객체 접근 연산자인 도트(.)를 사용했을 때 발생 |
| ArrayIndexOutOfBoundsException | 배열에서 인덱스 범위를 초과하여 사용할 때 발생 |
| NumberFormatException | 숫자로 변환할 수 없는 문자열을 숫자로 변경할 때 발생 |
| ClassCastException | 허용되지 않는데 억지로 타입 변환을 시도할 경우 발생 (ex. 부모 클래스를 자식 클래스로 타입 변환 시도) |
| IllegalArgumentException | 적합하지 않거나(illegal) 적절하지 못한(inappropriate) 인자를 메소드에 넘겨주었을 때 발생 |
| ArithmeticException | 예외적인 산술 조건이 발생했을 때 (ex. 0으로 나누기) |
예외 메시지를 String 형태로 제공받는다. 예외가 출력되었을 때 어떤 예외가 발생되었는지를 확인할 때 매우 유용하다. 즉, 그 메시지를 활용하여 별도의 예외 메시지를 사용자에게 보여주려고 할 때 좋다.
예외 메시지를 String 형태로 제공받는다. 그런데, getMessage() 메소드보다는 약간 더 자세하게, 예외 클래스 이름도 같이 제공한다.
가장 첫 줄에는 예외 메시지를 출력하고, 두 번째 줄부터는 예외가 발생하게 된 메소드들의 호출 관계(스택 트레이스)를 출력해준다.
try : 예외 발생 가능성이 있는 로직이 포함된 블럭
catch : 예외가 발생했을 때 처리되는 로직이 포함된 블럭
finally : 예외가 발생하던 안하던 최종적으로 처리되는 로직이 포함된 블럭
[예외에 대한 책임 전가]
📍 throw
public void divide(int num1, int num2) {
if (num2 == 0) {
throw new ArithmeticException("Divide by zero error");
}
int result = num1 / num2;
System.out.println("Result: " + result);
}
📍 throws
import java.io.IOException;
public class FileReader {
public void readFile() throws IOException {
// 파일을 읽는 작업
// IOException이 발생할 수 있음
}
public static void main(String[] args) {
FileReader reader = new FileReader();
try {
reader.readFile();
} catch (IOException e) {
System.out.println("파일 읽기 오류: " + e.getMessage());
}
}
}
final int MAX_RETRY = 100;
public Object someMethod() {
int maxRetry = MAX_RETRY;
while(maxRetry > 0) {
try {
...
} catch(SomeException e) {
// 로그 출력. 정해진 시간만큼 대기한다.
} finally {
// 리소스 반납 및 정리 작업
}
}
// 최대 재시도 횟수를 넘기면 직접 예외를 발생시킨다.
throw new RetryFailedException();
}
public void method1(){
try {
method2(); // throws가 붙은 method2는 반드시 이렇게 try문 안에서 호출되어야 함.
// method2가 떠넘긴 예외를 아래 catch문을 통해 처리
}
catch (ClassNotFoundException e1) {
System.out.println("클래스가 존재하지 않습니다.");
}
public void method2() throws ClassNotFoundException {
Class class = Class.forName("java.lang.String22");
}

// 조금 더 명확한 예외로 던진다.
public void add(User user) throws DuplicateUserIdException, SQLException {
try {
// ...생략
} catch(SQLException e) {
if(e.getErrorCode() == MysqlErrorNumbers.ER_DUP_ENTRY) {
throw DuplicateUserIdException();
}
else throw e;
}
}
// 예외를 단순하게 포장한다.
public void someMethod() {
try {
// ...생략
}
catch(NamingException ne) {
throw new EJBException(ne);
}
catch(SQLException se) {
throw new EJBException(se);
}
catch(RemoteException re) {
throw new EJBException(re);
}
}
서버쪽 시스템 오류를 메세지로 사용자에게 보여주게 되면, 심각한 보안적인 사고를 초래할 수 있다. 따라서 에러메세지를 사용자에게 보내주면 안될 때 오류를 파일 형식으로 저장할 수 있는 로깅 시스템을 사용한다.