✔️ 오류(Error)
오류(Error)는 시스템이 종료되어야 할 수준의 상황과 같이 수습할 수 없는 심각한 문제를 의미한다. 개발자가 미리 예측하여 방지할 수 밖에 없다.
✔️ 예외(Exception)
예외(Exception)는 개발자가 구현한 로직에서 발생한 실수나 사용자의 영향에 의해 발생한다. 오류와 달리 개발자가 미리 예측하여 방지할 수 있기에 상황에 맞는 예외처리(Exception Handle)를 해야 한다.
예외가 발생하면 프로그램이 종료가 된다는것은 에러와 동일하지만 예외는 예외처리(Exception Handling)을 통해 프로그램을 종료 되지 않고 정상적으로 작동되게 만들어줄 수 있다.
자바에서 예외처리는 Try Catch문을 통해 해줄 수 있다.
✅ 자바에서 예외 처리 계층의 루트 클래스
throw
키워드로 발생시킬 수 있는 건 전부 Throwable
의 자식이어야 함getMessage()
→ 예외 메시지 확인printStackTrace()
→ 예외 발생 경로 출력toString()
→ 예외 클래스명 + 메시지 출력OutOfMemoryError
(메모리 부족)StackOverflowError
(재귀 너무 깊음)👉 오류는 "잡아서 처리하려고 하지 말고, 근본적으로 코드/환경을 고쳐야 하는 문제"
✔️ StackOverflowError
: 응용 프로그램이 너무 많이 반복되어 StackOverflow가 발생할 때 던져지는 오류이다.
✔️ OutOfMemoryError
: JVM이 할당된 메모리의 부족으로 더 이상 객체를 할당할 수 없을 때 던져지는 오류이다.
- Garbage Collector에 의해 추가적인 메모리가 확보되지 못하는 상황일 때
- heap 사이즈 부족
- 너무 많은 class를 로드할 때
- 가용가능한 swap이 없을 때
- 큰 메모리의 native메서드가 호출될 때
이를 해결하기 위해, dump파일분석, jvm 옵션 수정 등이 있다.
앞서 말했듯 개발자가 미리 오류를 대처하기는 힘들다.
다만 StackOverflowError
를 피하기 위해서 재귀를 사용할 때에 조심하거나 가시적인 loop를 사용하는 간접적인 예방이 가능하다.
또한 OutOfMemoryError
를 피하기 위해 새는 메모리를 차단하거나 heap의 크기를 늘려주는 방법을 사용할 수도 있다.
NullPointerException
(null 접근)IOException
(파일 못 찾음)ArithmeticException
(0으로 나눔)👉 예외는 try-catch로 잡아서 프로그램이 죽지 않게 처리할 수 있음 ✅
1. Checked Exception
try-catch로 감싸거나 throw로 던져서 예외처리.
2. UncheckedException
RuntimeException
하위의 모든 예외NullPointerException
, IndexOutOfBoundException
등등❗️ Checked Exception과 UncheckedException의 가장 명확한 구분 기준
: '꼭 처리를 해야 하는가'
✔️ ArithmeticException
: 정수를 0으로 나눌경우 발생
✔️⭐️ ArrayIndexOutOfBoundsException
: 배열의 범위를 벗어난 index를 접근할 시 발생ex) 길이가 3인
int[]arr = new int[3]
배열을 선언했다면,
0 ~ 2까지의 index만 사용할 수 있다. 하지만 이 배열의 index가 -1이나 3을 참조하는 순간 이 예외가 발생한다.
✔️⭐️⭐️ ClassCastException
: 변화할 수 없는 타입으로 객체를 반환 시 발생타입 변환은 상위클래스와 하위클래스간에 발생하고 구현 클래스와 인터페이스간에도 발생한다. 이런 관계가 아니면 클래스는 다른 클래스로 타입을 변환할 수 없다. 하지만 이 규칙을 무시하고 억지로 타입을 변환시킬 경우 발생하는 예외이다.
✔️⭐️⭐️⭐️ NullPointException
: 존재하지 않는 레퍼런스를 참조할 때 발생Java 프로그램에서 가장 빈번하게 발생하는 익셉션으로, 객체 참조가 없는 상태, 즉 null값을 갖는 참조변수로 객체 접근 연산자인 토드(.)를 사용했을 때 발생한다.
객체가 없는 상태에서 객체를 사용하려 했으니 예외가 발생하는 것.
✔️ IllegalArgumentException
: 잘못된 인자를 전달할 때 발생
✔️ IllegalStateException
: 객체의 상태가 메서드 호출에는 부적절한 경우에 발생
✔️ IOException
: 입출력 동작 실패 또는 인터럽트 시 발생
✔️ OutOfMemoryException
: 메모리가 부족한 경우 발생
✔️⭐️⭐️ NumberFormatException
: 문자열이 나타내는 숫자와 일치하지 않는 타입의 숫자로 변환시 발생개발을 하다보면 문자열로 되어있는 데이터를 숫자타입으로 변경하는 경우가 자주 발생하는데 숫자타입으로 변경할 수 없는 문자를 치환시키려고 하면 발생하는 예외이다.
✔️ CurrentModificationException
: 금지된 곳에서 객체를 동시에 수정하는 것이 감지될 경우 발생
✔️ UnsupportedOperationException
: 객체가 메서드를 지원하지 않는 경우 발생
구분 | Error | Exception |
---|---|---|
의미 | 시스템 레벨 문제 | 프로그램 레벨 문제 |
복구 | 불가능 | 가능 (try-catch) |
예시 | OutOfMemoryError | NullPointerException |
처리 | 코드로 못 잡음 | 코드로 처리 가능 |
Java에서 모든 예외가 발생하면 (XXX)Exception 객체를 생성한다.
즉, 자바의 예외 처리는 발생시키기(throw), 던지기(throws), 잡아서 처리하기(try-catch-finally), 직접 정의하기(Custom Exception) 이 네 가지 흐름으로 정리할 수 있다 🚀
👉 코드 안에서 강제로 예외 객체를 만들어 발생시킴
public class ThrowExample {
public static void main(String[] args) {
int age = 15;
if (age < 18) {
throw new IllegalArgumentException("18세 미만은 접근 불가!");
}
System.out.println("접근 허용");
}
}
✔️ throw
뒤에는 반드시 Throwable
을 상속받은 객체가 와야 함
👉 메서드 선언부에 "이 메서드는 이런 예외를 던질 수 있다"고 선언하는 것
👉 호출한 쪽에서 예외를 처리해야 함
import java.io.FileReader;
import java.io.IOException;
public class ThrowsExample {
public static void main(String[] args) {
try {
readFile();
} catch (IOException e) {
System.out.println("파일을 읽는 중 오류 발생: " + e.getMessage());
}
}
public static void readFile() throws IOException {
FileReader fr = new FileReader("없는파일.txt"); // 예외 발생
}
}
✔️ throws
는 예외를 던지는 선언, 실제 발생은 throw
로 함
👉 예외가 발생할 수 있는 코드 블록을 감싸고, 예외 발생 시 처리
👉 finally는 무조건 실행됨 (자원 해제용)
public class TryCatchFinallyExample {
public static void main(String[] args) {
try {
int[] arr = {1, 2};
System.out.println(arr[5]); // 예외 발생
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("배열 인덱스 범위 초과!");
} finally {
System.out.println("항상 실행됨 (자원 해제 용도)");
}
}
}
✔️ try-catch
만 쓸 수도 있고, try-finally
만 쓸 수도 있음
👉 Exception
(Checked) 또는 RuntimeException
(Unchecked)을 상속받아 내가 원하는 예외를 만들 수 있음
// 나만의 예외 정의
class MyCheckedException extends Exception {
public MyCheckedException(String message) {
super(message);
}
}
public class CustomExceptionExample {
public static void main(String[] args) {
try {
checkAge(15);
} catch (MyCheckedException e) {
System.out.println("예외 발생: " + e.getMessage());
}
}
static void checkAge(int age) throws MyCheckedException {
if (age < 18) {
throw new MyCheckedException("18세 미만은 접근 불가!");
}
}
}
✔️ Checked Exception → 반드시 throws
로 선언하고 try-catch
로 처리해야 함
✔️ Unchecked Exception → RuntimeException
상속, 선언 안 해도 됨