컴퓨터 하드웨어의 고장으로 인해 응용프로그램 실행 오류가 발생하는 것을 자바에서는 에러(error)라고 한다. 프로그램을 아무리 견고하게 만들어도 개발자는 이런 에러에 대처할 방법이 전혀 없다.
자바에서는 에러 이외에 예외(exception)라고 부르는 오류가 있다. 예외란 잘못된 사용 또는 코딩으로 인한 오류를 말한다. 예외가 발생되면 프로그램은 곧바로 종료된다는 점에서는 에러와 동일하지만, 예외 처리를 통해 계속 실행 상태를 유지할 수 있다.
💠예외 종류
- 일반 예외 (Exception)
- 컴파일러가 예외 처리 코드 여부를 검사하는 예외를 말한다. (컴파일러가 체크)
- 실행 예외 (Runtime Exception)
- 컴파일러가 예외 처리 코드 여부를 검사하지 않는 예외를 말한다. (컴파일러가 체크하지 않음)
자바는 예외가 발생하면 예외 클래스로부터 객체를 생성한다. 이 객체는 예외 처리 시 사용된다. 자바의 모든 에러와 예외 클래스는 Throwable을 상속받아 만들어지고, 추가적으로 예외 클래스는 java.lang.Exception 클래스를 상속받는다.
실행 예외는 RuntimeException과 그 자식 클래스에 해당한다. 그 밖의 예외 클래스는 모두 일반 예외이다. 자바는 자주 사용되는 예외 클래스를 표준 라이브러리로 제공한다. 앞의 그림에서 언급한 모든 예외 클래스는 표준 라이브러리에서 제공하는 것들이다.
정리하자면,
- 일반 예외 (Exception)
- Exception을 상속받지만 RuntimeException을 상속받지 않는 클래스들
- Exception의 자식 클래스로 선언
- 실행 예외 (Runtime Exception)
- Exception을 상속받은 java.lang.RuntimeException의 상속을 받는 클래스들
- RuntimeException의 자식 클래스로 선언
💻 예외 처리 코드
예외가 발생했을 때 프로그램의 갑작스러운 종료를 막고 정상 실행을 유지할 수 있도록 처리하는 코드를 예외 처리 코드라고 한다.
예외 처리 코드는 try-catch-finally 블록으로 구성된다. try-catch-finally 블록은 생성자 내부와 메소드 내부에서 작성된다.
try-catch-finally 블록
- try 블록에서 작성한 코드가 예외 없이 정상 실행되면 catch 블록은 실행되지 않고 finally 블록이 실행된다.
- try 블록에서 예외가 발생하면 catch 블록이 실행되고 연이어 finally 블록이 실행된다.
- 예외 발생 여부와 상관없이 finally 블록은 항상 실행된다. 심지어 try 블록과 catch 블록에서 return문(메소드 종료)을 사용하더라도 finally 블록은 항상 실행된다. finally 블록은 옵션으로 생략 가능한다.
🔎 실행 예외 (Runtime Exception) 예제 코드
- 실행 예외 (Runtime Exception)는 컴파일 할 때 예외 처리 코드가 없어도 된다.
다음 예제에서 printLength() 메소드는 문자열의 수를 리턴한다. 12라인에서 문자열 대신 null을 입력하면 5라인에서 NullPointerException이 발생한다. NullPointerException은 참조 변수가 null인 상태에서 필드나 메소드에 접근할 경우 발생한다. NullPointerException은 실행 예외이므로 컴파일 할 때 예외 처리 코드가 없어도 되지만, 실행중에 발생하면 프로그램은 즉시 종료된다.
//ExceptionHandlingExample1.java
package ch11.sec02.exam01;
public class ExceptionHandlingExample1 {
public static void printLenght(String data) {
int result = data.lenght(); ⬅️ //data가 null일 경우 NullPointerException 발생
System.out.println("문자 수 : "+result);
}
public static void main(String[] args) {
System.out.println("[프로그램 시작]\n");
printLenght("ThisIsJava");
printLength(null); ⬅️ // 매개값으로 null을 대입
System.out.println("[프로그램 종료]");
}
}
🔎 일반 예외 (Exception) 예제 코드
- 소스가 컴파일되려면 예외 처리 코드르 반드시 작성해야 한다.
다음 예제에서 Class.forName("패키지···클래스")은 ClassPath 위치에서 주어진 클래스를 찾는 코드이다. 찾지 못했을 경우, ClassNotFoundException이라는 일반 예외가 발생한다. 따라서 소스가 컴파일되려면 예외 처리 코드르 반드시 작성해야 한다.
//ExceptionHandlingExample.java
package ch11.sec02.exam02;
public class ExceptionHandlingExample {
public static void main(String[] args) {
try {
Class.forName("java.lang.String"); ⬅️ // ClassNotFoundException 발생 가능 코드
System.out.println(("java.lang.String 클래스가 존재합니다.");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println();
try {
Class.forName("java.lang.String2"); ⬅️ // ClassNotFoundException 발생 가능 코드
System.out.println(("java.lang.String2 클래스가 존재합니다.");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
💻 예외 떠넘기기
메소드 내부에서 예외가 발생할 때 try-catch 블록으로 예외를 처리하는 것이 기본이지만, 메소드를 호출한 곳으로 예외를 떠넘길 수도 있다. 이때 사용하는 키워드가 throws이다. throws는 메소드 선언부 끝에 작성하는데, 떠넘길 예외 클래스를 쉼표로 구분해서 나열해주면 된다.
리턴타입 메소드명(매개변수, ···) throws 예외클래스1, 예외클래스2, ··· {
}
throws 키워드가 붙어 있는 메소드에서 해당 예외를 처리하지 않고 떠넘겼기 때문에 이 메소드를 호출하는 곳에서 예외를 받아 처리해야 한다. 예를들어 다음 코드는 ClassNotFoundException을 throws하는 findClass()의 예외를 main에서 호출할 때 처리하고 있다.
// ThrowsExample1.java
package ch11.sec05;
public class ThrowsExample1 {
public static void main(String[] args) {
try { ⬅️ // 호출한 곳에서 예외 처리
findClass(); ⬅️
} catch (ClassNotFoundException e) { ⬅️
System.out.println("예외 처리 : "+e.toString()); ⬅️
} ⬅️
}
public static void findClass() throws ClassNotFoundException { ⬅️ // 예외 떠넘기기
Class.forName("java.lang.String2");
}
}
https://blog.naver.com/ju_ble/223450524442
네이버 블로그에 2024. 5. 18. 12:16 작성했던 글을 티스토리에 보기 편하게 옮김 !
'기술 노트' 카테고리의 다른 글
[백준-깃허브] 백준과 깃허브 연동하기, 자동 커밋, 백준허브 (0) | 2024.11.13 |
---|---|
[깃허브] 깃허브(Github) 리드미 3D 잔디 꾸미기 (7) | 2024.09.24 |
[Study] 스프링 시큐리티(Spring Security) (2) | 2024.09.23 |
IT[Study] 깃 브랜치 전략(git-branch-strategy) (11) | 2024.09.23 |
[Study] 디자인 패턴(Design Pattern) (2) | 2024.09.23 |