Java

11. 자바 예외 처리(실행 예외, 예외 처리 코드, 사용자 정의 예외)

문정훈 2022. 2. 16. 23:44

1. 오류란?

오류의 종류 : 에러, 예외
에러는 JUM 실행에 문제가 생긴 것이므로 대처 못함
예외는 사용자의 잘못된 조작 도는 개발자의 잘못된 코딩으로 인해 발생하는 프로그램 오류를 말함 예외가 발생되면 프로그램은 곧바로 종료된다. 예외처리를 통해 플그램을 종료하지 않고 정상 실행 상태가 유지되도록 할 수 있다.


 

 

2. 예외 클래스

예외에는 두 가지 종류가 있다. 

=> 일반 예외, 실행 예외

 

모든 예외 클래스는 Exception을 상속받는다.

Exception을 상속받고 RuntimeException을 상속받지 않는 예외 클래스(ClassNotFoundException 같은 클래스)들을 일반 예외 클래스라고 하며 RuntimeExcepiton을 상속받은 예외 클래스를 실행 예외 클래스라고 한다. 


 

 

 

3. 예외의 2가지 종류

1) 일반 예외

컴파일러 체크 예외라고도 하며 일반 예외는 Exception 에외 클래스를 상속 받지만, RuntimeException은 상속받지 않는 크래스를 말한다. (실행 예외는 RuntimeException을 상속받은 클래스이다.)

try catch 문으로 작성을 무조건 해줘야한다. 

 

2) 실행 예외

RuntimeException 클래스를 상속한 예외 클래스를 생성 시키는 예외로 비어있는 객체 변수로 매소드를 접근하는 것과 같이 발생해서는 안되는 코드에 대해 발생하는 예외이다. 
예를 들어 
String date = null;
date.toString();
이렇게 되면 JVM은 예외에 해당하는 클래스(Java.lang.classNotFoundException)를 생성 시키고 프로그램을 강제 종료 한다. 


 

 

 

 

4. 예외 클래스의 내부 구조 및 작동 원리

1) Exception의 내부 구조

일반 예외들은 모두 Exception을 상속받는다. 이후 알아볼 사용자 정의 예외를 만들 떄 역시 Exception을 상속하면서 예외 클래스를 만들게 된다. 

Exception의 내부 메소드를 간단히 보면 두 생성자를 볼 수 있는데 String 타입으로 매개변수가 하나 있는 생성자를 볼 수 있다. 해당 생성자는 Exception의 부모 클래스인 Throwable 클래스에게 전달된다.

아래를 보면

 

Exception의 생성자로 전달되는 message는 Thorwable의 detailMessgae라는 필드에 저장되게 된다. 

 

 

2) 일반 예외 : Thread.sleep 예시

Exception의 내부 구조를 살펴봤으니 일반 예외 중 하나인 Sleep메소드를 예로 보면

Thread.sleep의 내부 구조는 위와 같다. 위 구조를 설명하면 sleep라는 메소드는 if문을 통해 예외 객체를 생성시킨다.

throw new 연산자를 통해 IllegaArgumentException이라는 예외 객체를 생성시킨다. 

이 IllegaArgumentException 객체는 InterruptedException을 상속받으며 InterruptedException은 최종적으로 Exception을 상속하므로 결국 IllegaArgumentException는 일반 예외임을 알 수 있다. 

IllegaArgumentException("문자열"); 이렇게 생성자의 매개변수로 문자열을 전달함을 알 수 있다. 

해당 문자열은 Exception이 상속하는 Throwable의 detailMessage의 필드에 저장되게 된다. 

sleep 메소드는 throws 키워드를 통해 예외 객체를 던지는 메소드가 된다. (sleep을 호출한 곳에서 InterruptedException 예외 객체를 try-catch문으로 받아줘야한다.)

 

 

만약 위와 같이 sleep의 에외 객체를 메인 메소드 내부에서 try-catch문으로 처리하지 않고 메인 메소드 역시 throws로 예외 객체를 던져버린다면 결국 JVM이 마지막으로 처리를 한다. 

이렇게 메인 메소드가 던지면 메인 메소드에서 실행 되는 모든 일반 예외는 try 문을 선언 할 필요 없어지게 된다.

 

 

3) 실행 예외 

이와 같은 예시에서 실행 예외가 발생하게 되는데 실행 예외는 try catch문을 작성하지 않아도 컴파일 오류가 발생하지 않는다. 하지만 위와 같이 실행 예외가 발생할 가능성이 있는 코드에서는 try-catch문을 작성해야할 판단을 직접해서 적어줘야한다.
실행 예외를 발생 시키는 메소드 내부에 예외 발생 객체 생성 코드인 throw new 가 포함된 문장은 어디에있는건가?
일반 예외는 예외가 발생될 메소드 안에 if문 등과 같은 코드를 통해 throw new 문장이 포함되있으나 실행예외는 어디있음? 답은 JVM에서 실행 예외가 발생되면 JVM이 예외 객체를 만들고 콘솔 창에 띄우고 프로그램을 종료함 


 

 

 

 

5. 예외 처리 코드 (try-catch-finally) 문법

1) 기본 문법

catch의 매개 변수는 try 문에서 발생 되어 날라오는 예외 객체를 받는 매개변수로 
catch문의 내용으로 두 메소드를 호출함을 알 수 있다.

getMessage, printStackTrace 메소드 모두 Throwable 클래스의 메소드이다.

getMessage 메소드를 호출 시켜 Throwable 의 필드인 detailmessage의 내용을 콘솔에 출력한다.
try 문에서 발생 되지 않을 예외클래스 타입을 catch문의 매개변수로 넣으면 컴파일 오류가 난다.

 

 

2) 멀티 catch문

catch문은 아래로 줄을 지어 작성할 수 있다. catch문은 위에서 아래로 실행된다.

따라서 catch문을 작성할때 위쪽에는 디테일한 예외 클래스를 작성하며 아래로 내려갈 수 록 Exception에 가까운 예외 객체를 적어주는 것이 좋다. 


 

 

 

 

 

6. 사용자 정의 예외(일반 예외 만들기)

Exception의 내부구조를 다시보자.

사용자가 직접 일반 예외 클래스를 만들 때는 Exception을 상속하는 것으로 부터 시작한다. 

 

위 클래스는 예외 클래스를 만든 것이다. 

위 예외 클래스를 어떤 임의의 메소드에서 thorw new User_error_class("사용자 정의 예외입니다"); 이 와 같이 예외 객체를 발생 시킬 수 있다.  아래 코드를 보자. 

 

Circle이라는 클래스가 있고 메소드로 method() 메소드가 있다. 

method 메소드는 반지름 값이 음수이면 예외 클래스인 User_error_class의 객체를 throw new 연산자를 통해 생성시키고 method 함수를 호출한 곳(메인 메소드)로 사용자 정의 예외 객체를 던져버린다. 

메인 메소드에서는 일반 예외가 발생할 수 있는 메소드인 method를 호출하므로 try-catch문을 작성하여 생성된 예외 객체를 처리해줘야한다. 

 

'Java' 카테고리의 다른 글

13. 컬렉션 프레임워크  (0) 2022.03.30
12. 자바 API 클래스  (0) 2022.02.17
10. 중첩 클래스  (0) 2022.02.06
9. 인터페이스  (0) 2022.02.06
8. 상속  (0) 2022.02.06