[Java] Ch08. 예외처리(exception handling)

토끼는 개발개발·2022년 2월 4일
0

Java

목록 보기
32/33
post-thumbnail

Chapter08. 예외처리(exception handling)


1.1 프로그램 오류

컴파일 에러 : 컴파일 시에 발생하는 에러
런타임 에러 : 실행 시에 발생하는 에러
논리적 에러 : 실행은 되지만, 의도와 다르게 동작하는 것

에러(error) : 프로그램 코드에 의해서 수습될 수 없는 심각한 오류
예외(exception) : 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류




1.2 예외 클래스의 계층 구조


자바에서는 실행 시 발생할 수 있는 오류(Exception과 Error)를 클래스로 정의하였다. 앞서 배운 것처럼 모든 클래스의 조상은 Object클래스이므로 Exception과 Error클래스 역시 Object클래스의 자손들이다.

모든 예외 최고 조상은 Exception클래스이며, 예외 클래스들은 다음과 같이 두 그룹으로 나눠질 수 있다.

Exception클래스들 : 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외
RuntimeException : 프로그래머의 실수로 발생하는 예외




1.3 예외처리하기 - try-catch문

예외처리(Exception handling)
- 정의 : 프로그램 실행시 발생할 수 있는 예외에 대비한 코드를 작성하는 것
- 목적 : 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지하는 것

try {
	//예외가 발생할 가능성이 있는 문장들을 넣는다.
} catch (Exception1 e1) {
	//Exception1이 발생했을 경우, 이를 처리하기 위한 문장을 적는다.
} catch (Exception2 e2) {
	//Exception2이 발생했을 경우, 이를 처리하기 위한 문장들을 적는다.
} catch (Exception3 e3) {
	//Exception3이 발생했을 경우, 이를 처리하기 위한 문장들을 적는다.
}

▶ ✨ 예제 1


public class ExceptionEx1 {

	public static void main(String[] args) {
		int number = 100;
		int result = 0;
		
		for(int i=0; i < 10; i++) {
			result = number / (int)(Math.random() * 10);
			System.out.println(result);
		}
	}
}

해당 예제는 변수 number에 저장되어 있는 값 100을 0~9사이의 임의의 정수로 나눈 결과를 출력하는 일을 10번 반복한다.

에러 메시지를 보면, 0으로 나누려 했기 때문에 에러가 발생한 것을 알 수 있다. ArithmeticException은 산술연산과정에서 오류가 있을 때 발생하는 예외이다. 정수는 0으로 나누는 것이 금지되어 있기 때문에 발생했다. 하지만, 실수를 0으로 나누는 것은 금지되어있지 않으며 예외가 발생하지 않는다.

이제 try-catch문을 추가해서 비정상적 종료되지 않도록 수정해보자.


public class ExceptionEx3 {

	public static void main(String[] args) {
		int number = 100;
		int result = 0;
		
		for(int i=0; i < 10; i++) {
			try {
				result = number / (int)(Math.random() * 10);
				System.out.println(result);
			} catch (ArithmeticException e) {
				System.out.println("0"); //ArithmeticException이 발생하면 실행되는 코드
			}
		}

	}

}

▶ 모든 예외 처리

catch블럭의 괄호()에 Exception클래스 타입의 참조변수를 선언해 놓으면 어떤 종류의 예외가 발생하더라도 이 catch블럭에 의해 처리된다.

catch (Exception e) { }

▶ 멀티 catch블럭

'|' 기호를 이용해 하나의 catch 블럭으로 합칠 수 있다. '|' 기호로 연결할 수 있는 예외 클래스의 개수에는 제한이 없다.

try {
	...
} catch (ExceptionA e) {
e.printStackTrace();
} catch (ExceptionB e2) {
e2.printStackTrace();
}

                ▼

try{
	...
} catch (ExceptionA | ExceptionB e) {
e.printStackTrace();
}

만일 멀티 catch블럭의 '|' 기호로 연결된 ㅋ예외 클래스가 부모 자식의 관계에 있다면 컴파일 에러가 발생한다. 두 예외 클래스가 부모 자식의 관계라면 부모 클래스만 써주어도 되기 때문이다.


▶ PrintStackTrace()와 getMessage()

printStackTrace() : 예외발생 당시의 호출스택(Call Stack)에 있었던 메서드의 정보와 예외 메시지를 화면에 출력한다.
getMessage(): 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있다.




1.4 메서드에 예외 선언하기

void method() throws Exception1, Exception2, ..., ExceptionN {
//메서드의 내용
}

메서드에 예외를 선언하려면, 메서드의 선언부에 키워드 throws를 사용해서 메서드 내에서 발생할 수 있는 예외를 적어주기만 하면 된다. 그리고 예외가 여러 개일 경우에는 쉼표로 구분한다. 이렇게 예외를 선언하면, 이 예외뿐만 아니라 그 자식타입의 예외까지도 발생할 수 있다는 점에 주의하자.

메서드의 선언부에 예외를 선언함으로써 메서드를 사용하려는 사람이 메서드의 선언부를 보았을 때, 이 메서드를 사용하기 위해서는 어떤 종류의 예외가 발생할 가능성이 있는지 충분히 예측하기 힘들기 때문에 그에 대한 대비를 하는 것이 어려웠다.

그러나 자바에서는 작성할 때 메서드 내에서 발생할 가능성이 있는 예외를 메서드의 선언부에 명시하여 이 메서드를 사용하는 쪽에서 이에 대한 처리를 하도록 강요하기 때문에, 프로그래머들의 짐을 덜어 주는 것은 물론이고 보다 견고한 프로그램 코드를 작성할 수 있도록 도와준다.




1.5 finally블럭

finally 블럭은 예외의 발생여부에 상관없이 실행되어야할 코드를 포함시킬 목적으로 사용된다.
try-catch문의 끝에 선택적으로 덧붙여 사용할 수 있다.


try {
	//예외가 발생할 가능성이 있는 문장들을 적는다.
} catch (Exception e1) {
	//예외처리를 위한 문장을 적는다.
} finally {
	//예외의 발생여부에 관계없이 항상 수행되어야하는 문장들을 넣는다.
    //finally블럭은 try-catch문의 맨 마지막에 위치해야한다.
}

예외가 발생한 경우에는 'try -> catch -> finally' 순으로 실행되고,
예외가 발생하지 않은 경우에는 'try -> finally' 순으로 실행된다.




참고서적
자바의 정석(저자: 남궁성)


오늘의 한 줄

java의 정석 포스팅을 28번째 이 포스팅을 마지막으로 마무리 한다.

1월 한 달 동안 꾸준히 python 코딩테스트와 java언어를 공부하며 포스팅을 올렸다.
이제는 java 코딩테스트와 Spring프레임워크 사용으로 넘어가겠다.

이제 본격적으로 시작이다!

profile
하이 이것은 나의 깨지고 부서지는 기록들입니다

0개의 댓글