본문 바로가기

JAVA

[Java] 4-1강 - 예외 처리

cf> error의 종류

compile error : compile에 안 된다. (e.g. syntax error)

run-time error : compile은 잘 되는데 프로그램 실행 시에 문제가 된다.

logical error : computer는 error인지 모르는데, 프로그래머가 생각하는 대로 코드가 돌지 않는다.

 

0. Background

1) Run-time error

Run-time error는 error와 exception으로 분류할 수 있습니다.

1> error 

더 이상 프로그램을 지속할 수 없는 경우

e.g. out of memory

 

2> exception

프로그램을 종료하지 않아도 되는 경우

e.g. arithmetic exception, class cast exception, null pointer exception, index out-of-bounds exception, etc.

 

2) Error & Exception

java에서는 error와 exception는 class로 정의되어 있습니다. 

 

0> Throwable

Object 아래에 Throwable class가 있고 

Throwable 아래 Error와 Exception class가 있습니다.

Exception 아래 RuntimeException class가 있습니다.

 

1> RuntimeException

주로 프로그래머의 실수에 의해 발생하는 것들입니다.

e.g. ArrayIndexOutOfBoundsException, NullPointerException, ClassCastException, Arithmetic Exception, etc

 

2> other exception 

주로 환경적인 문제나 프로그램을 사용하는 user의 문제입니다.

e.g. FileNotFoundException, ClassNotFoundException, DataFormatException, etc.

 

1. Exception Handling: try-catch

1) 기본 형식

try {
	// error가 발생할 수 있는 구문
} catch (Exception1 e1) { // error의 한 종류를 넣는다.
	// e1 error가 발생하면 이 statement를 실행한다.
} catch (Exception2 e2) {
	// e2 error가 발생하면 이 statement를 실행한다.
try { } catch (Exception3 e3) { } // try-catch 구문은 중첩해서 사용할 수 있습니다.

} 

try block 내부를 실행하다가 error가 발생하면

그 즉시 try block 실행을 중단하고

catch들 중 일치하는 error로 가서 (동시에 exception의 object도 생성됩니다.)

해당하는 catch block을 실행합니다.

 

cf> 상세 예시

public class Lecture {
	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); 
                // error가 발생하면 그 즉시 catch로 갑니다.
				System.out.println(result);
			} catch (ArithmeticException e) {
				System.out.println("0");
			}
		}
	}
}

try 내부의 statement를 실행하다가 error가 발생하면

그 즉시 catch로 가서 발생한 error와 exception이 일치하면

그 catch 내부의 statement를 실행합니다.

 

※ 핵심은 try 내부는 error가 발생하면 끝까지 가지 않고 중단한다는 점입니다.

 

2) catch block

try {
	// error가 발생할 수 있는 구문
} catch (Exception1 e1) { // error의 한 종류를 넣는다.
	// e1 error가 발생하면 이 statement를 실행한다.
} catch (Exception2 e2) {
	// e2 error가 발생하면 이 statement를 실행한다.
try { } catch (Exception3 e3) { } // try-catch 구문은 중첩해서 사용할 수 있습니다.

} 

[1] error 발생 시 위의 catch부터 차례대로 확인하여

[2] 해당 error에 맞는 catch block으로 갑니다.

(만약에 첫 번째 catch block으로 갔다면)

[3] 그리고 (e1이라는) object를 생성합니다.

 

1> Exception class의 hierarchy

 

- 그래서 catch에 Exception을 사용하면 그 하위 exception이 발생해도 catch문을 실행할 수 있습니다.

- catch block은 위에서부터 하나씩 실행합니다.

2> 디버깅 method (Exception의 method)

- printStackTrace() : error가 났을 시점까지 사용한 method를 출력 (stack)

- getMessage() : exception관련 message (string)

 

3) finally block

try에서 error가 있어서 

catch에서 이 error에 해당하는 exception을 찾아봤지만 없는 경우

finally에 있는 statement를 실행합니다. 

 

cf> 다만 return이 try안에 있으면 finally block을 실행하고 return하는 경우가 있을 수 있으니

굳이 이렇게 코딩하지 않는 것을 권장합니다.

 

2. Methods that throw exceptions

cf> Generating an Exception

public class Lecture {
	public static void main(String args[]) {
		try {
			Exception e = new Exception("I created the exception."); // 0) 1>
			throw e; // 0) 2>
		} catch (Exception e) {
			System.out.println("exception message: " + e.getMessage());
			e.printStackTrace();
		}
		System.out.println("The program terminated normally.");
	}
}

1> exception instance를 만들고

2> throw(keyword)를 이용해서 원하는 exception을 만듭니다.

 

0) Mandatory and Optional Exception Handling

1> checked exception

- mandatory handling해야 합니다.

- RuntimeException을 제외한 Exception입니다.

예를 들어 FileNotFoundException은 파일이 없는 경우에 compile 과정에서 error가 납니다.

 

2> unchecked exception

- optional handling해야 합니다.

- RuntimeException에 해당하는 exception입니다. 

compile하는 과정에서 error가 없기 때문에 throw를 해야지만 error를 파악할 수 있습니다.

 

1) Method의 throw

method 내부에 exception이 있는 경우 특정 method는 실행해도 exception이 발생하지 않게 해주는 것

(마치 면죄부, 책임 전가와 같습니다.)

다만 method가 다른 method 내부에 쓰이면 throw의 책임 전가 효과가 발생하지 않습니다.

 

1>

- method2는 실행해도 문제가 안 되지만

- method1, main은 실행하면 exception이 발생합니다.

2> 

- method1, method2는 실행해도 문제가 안 되지만

- main은 실행하면 exception이 발생합니다.

3> 

- method1, method2, main은 실행하면 exception이 발생합니다.

4> 

5> 

FileOutputStream 자체에서는 FileNotFoundException을 throw하지만 

이를 다른 method 내부에서 사용하면 throw하지 못할 수 있습니다.

그래서 main method에서도 FileNotFoundException의 상위 Exception인 IOException을 throw합니다.