1. 프로그램 오류

- 컴파일 에러(compile-time error) : 컴파일할 때 발생하는 에러

- 런타임 에러(runtime error) : 실행할 때 발생하는 에러


2. 자바에서의 실행 시(runtime) 발생할 수 있는 프로그램 오류

- 에러(error) : 프로그램 코드에 의해서 수습될 수 없는 심각한 오류

- 오류(exception) : 프로그램 코드에 의해서 수습 될 수 있는 미약한 오류


3. 예외처리의 정의와 목적

- 정의 : 프로그램 실행 시 발생할 수 있는 예외의 발생에 대비한 코드를 작성하는 것

- 목적 : 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지하는 것


4. 예외처리구문

- 예외를 처리하려면 try - catch 문을 사용한다.

try {

/* 예외가 발생할 가능성이 있는 문장들을 넣는다. */

} catch (Exception1 e1) {

/* Exception1이 발생했을 경우, 이를 처리하기 위한 문장을 적는다. */

} catch (Exception2 e2) {

/* Exception2이 발생했을 경우, 이를 처리하기 위한 문장을 적는다. */

. . .

} catch (ExceptionN eN) {

/* ExceptionN이 발생했을 경우, 이를 처리하기 위한 문장을 적는다. */

}

- 하나의 try 블럭 다음에는 여러 종류의 예외를 처리할 수 있또록 하나 이상의 catch 블럭이 올 수 있다.

- try 블럭 또는 catch 블럭에 또 다른 try-catch 문이 포함 될 수 있다. (단, catch 블럭 내에 포함할 경우 참조변수를 다른이름으로 사용한다.)

public class ExceptionEx {
	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 : " + result);
			} catch (ArithmeticException e) {
				System.out.println("0 이 나와서 오류가 발생합니다.");
			} // try - catch
		} // for
		
	} // main
} // ExceptionEx

/*
 * 결과
 * 
 * 0 이 나와서 오류가 발생합니다.
 * result : 14
 * result : 100
 * result : 100
 * result : 25
 * result : 25
 * result : 33
 * result : 12
 * result : 11
 * 0 이 나와서 오류가 발생합니다.
 */


5. try-catch 문에서의 흐름

- try 블럭 내에서 예외가 발생한 경우

- 발생한 예외와 일치하는 catch 블럭이 있는지 확인한다.

- 일치하는 catch블럭을 찾게 되면, 그 catch 블럭 내의 문장들을 수행하고 전체 try-catch 문을 빠져나가서 그 다음 문장을 계속해서 수행한다.

- 일치하는 catch블럭을 찾지 못하면, 예외는 처리되지 못한다.

- try 블럭 내에서 예외가 발생하지 않은 경우

- catch 블럭을 거치지 않고 전체 try-catch 문을 빠져나가서 수행을 계속한다.


6. 예외 발생시키기

- 키워드 throw를 사용해서 프로그래머가 고의로 예외를 발생시킬 수 있다.

- 연산자 new를 이용해서 발생시키려는 예외 클래스의 객체를 만든다. : Exception e = new Exception("고의로 에러 발생");

- 키워드 throw를 이용해서 예외를 발생시킨다. : throw e;

public class ExceptionThrow {
	public static void main(String[] args) {
		try {
			Exception e = new Exception("고의로 발생 시킴");
			throw e; // 예외를 발생
			
			// throw new Exception("고의로 발생시켰음."); 위의 2줄을 이처럼 1줄로 줄여쓰기 가능하다.
		} catch (Exception e) {
			System.out.println("에러 메세지 : " + e.getMessage());
			e.printStackTrace();
		} // try - catch
		
		System.out.println("프로그램이 정상 종료됨");
	} // main
} // ExceptionThrow


7. 예외 클래스의 계층구조

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

- RuntimeException 클래스들 : 프로그래머의 실수로 발생하는 예외, 컴파시에 문제 되지 않음.

- Exception 클래스들 : 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외, 컴파일시에 에러 발생.


8. 예외의 발생과 catch 블럭

- try 블럭에서 예외가 발생하면, 발생한 예외를 처리한 catch 블럭을 찾는다.

- 첫번째 catch 블럭부터 순서대로 찾아 내려가며, 일치하는 catch 블럭이 없으면 예외는 처리되지 않는다.

- 예외의 최고 조상인 Exception을 처리하는 catch블럭은 모든 종류의 예외를 처리할 수 있다. (반드시 마지막 catch 블럭에 처리한다.)

- 발생한 예외 객체를 catch블럭의 참조변수로 접근할 수 있다.

- printStactTrace() : 예외발생 당시의 호출스택(Call stack)에 있었던 메서드의 정보와 예외 메세지를 화면에 출력한다.

- getMessage() : 발생한 예외 클래스의 인스턴스에 저장된 메세지를 얻을 수 있다.


9. finally 블럭

- 예외의 발생여부와 관계없이 실행되어야 하는 코드를 넣는다.

- 선택적으로 사용할 수 있다.

- try - catch - finally 순서로 구성된다.

- 예외 발생시 try - catch - finally 의 순서로 실행되고, 미발생시 try - finally 순서로 실행된다.

- try 또는 catch 블럭에서 return문을 만나도 finally 블럭은 수행된다.

public class FinallyTest {
	public static void main(String[] args) {
		FinallyTest.method();
		System.out.println("method() 의 수행을 마치고 main 메서드로 돌아옴");
	} // main
	
	static void method() {
		try {
			System.out.println("method() 호출");
			return; // 메서드 종료
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			System.out.println("method() 의 finally 블럭이 실행 됨");
		} // try - catch - finally
	} // method
	
} // FinallyTest

/*
 * 결과 
 * 
 * method() 호출
 * method() 의 finally 블럭이 실행 됨
 * method() 의 수행을 마치고 main 메서드로 돌아옴
 * 
 */

10. 메서드에 예외 선언하기

- 메서드 선언부에 throws를 사용해서 예외를 적어준다. 여러개일 경우는 쉼표(,)로 구분한다.

- 예외를 처리하는 것이 아니라, 호출한 메서드로 전달해주는 것

- 호출한 메서드에서 예외처리를 해야 할 때 사용

public class ThrowsTest {
	public static void main(String[] args) {
		try {
			sub();
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("배열의 크기가 잘못 되었습니다. 0 ~ 9 유효합니다.");
		}
	} // main
	
	public static void sub() throws ArrayIndexOutOfBoundsException {
		int[] array = new int[10];
		int i = array[10];
	}
} // ThrowsTest 

11. 예외 되던지기(exception re-throwing)

- 한 메서드에서 발생할 수 있는 예외가 여럿인 경우, 몇개는 try - catch 문으로 처리하고, 나머지는 호출한 메서드에서 처리하도록 함으로써 양쪽에서 나눠서 처리되도록 할 수 있다.

- 예외를 처리한 후에 다시 예외를 생성해서 호출한 메서드로 전달하는 것.

- 예외가 발생한 메서드와 호출한 메서드, 양쪽에서 예외를 처리해야 하는 경우에 사용한다.

public class RethrowingTest {
	public static void main(String[] args) {
		try {
			method();
		} catch (Exception e) {
			System.out.println("main 메서드에서 예외가 처리 됨");
		}// try - catch
	} // main
	
	static void method() throws Exception {
		try {
			throw new Exception();
		} catch (Exception e) {
			System.out.println("method 메서드에서 예외가 처리 됨");
			throw e; // 다시 예외를 발생시킨다.
		} // try - catch
	} // method
	
} // RethrowingTest

/* 
 * 결과
 * 
 * method 메서드에서 예외가 처리 됨
 * main 메서드에서 예외가 처리 됨
 * 
 */

11. 사용자정의 예외 만들기

- 기존의 정의된 예외 클래스를 상속받아서 새로운 예외 클래스를 정의할 수 있다.

class MyException extends Exception {
	public MyException(String message) {
		super(message);
	} // MyException 생성자
} // MyException extends Exception

public class MyExceptionTest {
	public static void checkNegative(int number) throws MyException {
		if (number < 0) {
			throw (new MyException("음수는 안됩니다."));
		}
		System.out.println("다행히 음수가 아니군요");
	}
	
	public static void main(String[] args) {
		try {
			checkNegative(1);
			checkNegative(-1);
		} catch (MyException ex) {
			ex.printStackTrace();
		} // try catch
	} // main
} // MyExceptionTest


+ Recent posts