1. 오류 메시지 출력 방법

e.printStackTrace() 를 이용한 오류 메시지 출력

'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
9

java.lang.ArrayIndexOutOfBoundsException: Index 9 out of bounds for length 8

 

e.getMessage() 를 이용한 오류 메시지 출력

이 방법은 오류 메시지를 String 타입으로 받아오기만 해서 e.printStackTrace처럼 바로 콘솔에 뿌려주지 않는다. 따라서 print를 직접 해줘야한다.

'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
9

Index 9 out of bounds for length 8 오류 발생

 

 

2. try ~ catch

에러가 발생할만한 곳에 try를 하고 에러를 catch로 잡는다.

모든 에러의 부모는 (Exception e)로 catch할 수 있으며, 각 에러 타입별로 catch하고 싶다면 아래와 같이 각 에러 타입별로 catch할 수 있다.
(ArrayIndexOutOfBoundsException e) : 
(InputMismatchException e) : 

import java.util.Scanner;
import java.util.InputMismatchException;

public class ExecClass {
	// 1. try ~ catch 를 활용한 exception 예외처리. (예외가 발생할만한 곳에 try 처리를 한다.)
	public static void main(String[] args) {
		ExTest exTest = new ExTest();
		try {
			exTest.doAction();
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println(e.getMessage());
		}
	}
	
//	// 2. throws Exception (예외가 발생 시 호출한 곳으로 가져와 처리를 한다.)
//	public static void main(String[] args){	// 처리할 곳이 있다면... throws Exception으로 ExTest의 doAction2에서 받아온 에러를 다시 위로 던질 수도 있다.
//		ExTest exTest = new ExTest();
//		Scanner scanner = new Scanner(System.in);
//		for (int i = 0; i < 99; i++) {
//			try {
//				exTest.doAction2();
//			} catch (ArrayIndexOutOfBoundsException e) {	// try에서 발생한 에러가 인덱스를 벗어난 경우를 catch한다. (인덱스 범위가 0~7인데 8이 들어오는 경우)
//				System.out.println("인덱스의 범위를 벗어났습니다. 0 ~ 7 사이로 입력해주세요.");
//			} catch (InputMismatchException e) {		// try에서 발생한 에러가 데이터 타입이 잘못된 경우를 catch한다. (문자에 숫자가 들어오거나, 숫자에 문자가 들어오는 경우)
//				scanner.nextLine();		// int에 잘못 들어와 소거되지 못 하고 무한루프를 발생시키는 문자 찌꺼기 소거용.
//				System.out.println("문자를 입력했습니다. 숫자를 입력해주세요.");
//			} catch (Exception e) {		// 모든 Exception의 부모형태다. 항상 마지막에는 Exception e로 끝내준다. 이 경우는 위에서 인덱스 범위 초과, 데이터 입 에러를 모두 잡아서 마지막 Exception e는 타지 않는다.
//										// 위에서 모든 에러를 잡았더라도 혹시 모를 에러에 대비하기 위해 마지막에 모든 에러의 부모형인 Exception e로 끝내줘야한다.
//				// 오류 출력 방법 1. e.printStackTrace()
//				e.printStackTrace();	// 프로그램이 죽지는 않고 에러메세지를 출력해준다.
//				// 오류 출력 방법 2. System.out.println(e.getMessage())
//				System.out.println(e.getMessage() + " 오류 발생");
//			}
//			System.out.println("------------------------------------");
//		}
//	}
}
import java.util.InputMismatchException;
import java.util.Scanner;

public class ExTest {
	// 1. try ~ catch 를 활용한 exception 예외처리. (예외가 발생할만한 곳에 try 처리를 한다.)
	public void doAction() {
		// TODO Auto-generated method stub
		int[] arr = {1, 2, 10, 390, 5, 20, 8, 7};
		Scanner scanner = new Scanner(System.in);
		
		// 1.1 try ~ catch 사용의 올바른 예
		for (int i = 0; i < 99; i++) {
			System.out.println("'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.");
			try {
				int inputNumber = scanner.nextInt();
				scanner.nextLine();		// nextInt return 찌꺼기 소거용.
				System.out.println("입력된 숫자에 해당되는 값은 " + arr[inputNumber]);
			} catch (ArrayIndexOutOfBoundsException e) {	// try에서 발생한 에러가 인덱스를 벗어난 경우를 catch한다. (인덱스 범위가 0~7인데 8이 들어오는 경우)
				System.out.println("인덱스의 범위를 벗어났습니다. 0 ~ 7 사이로 입력해주세요.");
			} catch (InputMismatchException e) {		// try에서 발생한 에러가 데이터 타입이 잘못된 경우를 catch한다. (문자에 숫자가 들어오거나, 숫자에 문자가 들어오는 경우)
				scanner.nextLine();		// int에 잘못 들어와 소거되지 못 하고 무한루프를 발생시키는 문자 찌꺼기 소거용.
				System.out.println("문자를 입력했습니다. 숫자를 입력해주세요.");
			} catch (Exception e) {		// 모든 Exception의 부모형태다. 항상 마지막에는 Exception e로 끝내준다. 이 경우는 위에서 인덱스 범위 초과, 데이터 입 에러를 모두 잡아서 마지막 Exception e는 타지 않는다.
										// 위에서 모든 에러를 잡았더라도 혹시 모를 에러에 대비하기 위해 마지막에 모든 에러의 부모형인 Exception e로 끝내줘야한다.
				// 오류 출력 방법 1. e.printStackTrace()
				e.printStackTrace();	// 프로그램이 죽지는 않고 에러메세지를 출력해준다.
				// 오류 출력 방법 2. System.out.println(e.getMessage())
				System.out.println(e.getMessage() + " 오류 발생");
			}
			System.out.println("------------------------------------");
		}
		
//		// 1.2 try ~ catch 사용의 잘못된 예
//		try {
//			int inputNumber = scanner.nextInt();
//			System.out.println("입력된 숫자에 해당되는 값은 " + arr[inputNumber]);
//		} catch (Exception e) {		// 얘는 위로 올라오면 안 된다. 모든 Exception의 부모이기 때문에 반드시 마지막으로 가야한다.
//			System.out.println("오류 발생");
//		} catch (ArrayIndexOutOfBoundsException e) {
//			System.out.println("인덱스의 범위를 벗어났습니다.");
//		} 
	}
	
	// 2. throws Exception (예외가 발생 시 호출한 곳으로 가져와 처리를 한다.)
	public void doAction2() throws Exception {	// 에러 발생시 호출한 곳으로 보낼거야.
		// TODO Auto-generated method stub
		int[] arr = {1, 2, 10, 390, 5, 20, 8, 7};
		System.out.println("'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.");
		Scanner scanner = new Scanner(System.in);
		
		int inputNumber = scanner.nextInt();	// 여기서는 에러 처리를 하지 않는다. 에러 발생시 호출한 곳으로 에러를 던진다.
		scanner.nextLine();		// nextInt return 찌꺼기 소거용.
		System.out.println("입력된 숫자에 해당되는 값은 " + arr[inputNumber]);
		
	}

}
결과 :

'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
7
입력된 숫자에 해당되는 값은 7
------------------------------------
'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
8
인덱스의 범위를 벗어났습니다. 0 ~ 7 사이로 입력해주세요.
------------------------------------
'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
a
문자를 입력했습니다. 숫자를 입력해주세요.
------------------------------------
'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.

 

 

3. throws exception

예외가 발생 시 호출한 곳으로 가져와 처리를 한다. (일반적으로 throws보다는 예외 발생 부분에서 surround try ~ catch를 하는게 좋다.)

import java.util.Scanner;
import java.util.InputMismatchException;

public class ExecClass {
//	// 1. try ~ catch 를 활용한 exception 예외처리. (예외가 발생할만한 곳에 try 처리를 한다.)
//	public static void main(String[] args) {
//		ExTest exTest = new ExTest();
//		try {
//			exTest.doAction();
//		} catch (Exception e) {
//			// TODO: handle exception
//			System.out.println(e.getMessage());
//		}
//	}
	
	// 2. throws Exception (예외가 발생 시 호출한 곳으로 가져와 처리를 한다.)
	public static void main(String[] args){	// 처리할 곳이 있다면... throws Exception으로 ExTest의 doAction2에서 받아온 에러를 다시 위로 던질 수도 있다.
		ExTest exTest = new ExTest();
		Scanner scanner = new Scanner(System.in);
		for (int i = 0; i < 99; i++) {
			try {
				exTest.doAction2();
			} catch (ArrayIndexOutOfBoundsException e) {	// try에서 발생한 에러가 인덱스를 벗어난 경우를 catch한다. (인덱스 범위가 0~7인데 8이 들어오는 경우)
				System.out.println("인덱스의 범위를 벗어났습니다. 0 ~ 7 사이로 입력해주세요.");
			} catch (InputMismatchException e) {		// try에서 발생한 에러가 데이터 타입이 잘못된 경우를 catch한다. (문자에 숫자가 들어오거나, 숫자에 문자가 들어오는 경우)
				scanner.nextLine();		// int에 잘못 들어와 소거되지 못 하고 무한루프를 발생시키는 문자 찌꺼기 소거용.
				System.out.println("문자를 입력했습니다. 숫자를 입력해주세요.");
			} catch (Exception e) {		// 모든 Exception의 부모형태다. 항상 마지막에는 Exception e로 끝내준다. 이 경우는 위에서 인덱스 범위 초과, 데이터 입 에러를 모두 잡아서 마지막 Exception e는 타지 않는다.
										// 위에서 모든 에러를 잡았더라도 혹시 모를 에러에 대비하기 위해 마지막에 모든 에러의 부모형인 Exception e로 끝내줘야한다.
				// 오류 출력 방법 1. e.printStackTrace()
				e.printStackTrace();	// 프로그램이 죽지는 않고 에러메세지를 출력해준다.
				// 오류 출력 방법 2. System.out.println(e.getMessage())
				System.out.println(e.getMessage() + " 오류 발생");
			}
			System.out.println("------------------------------------");
		}
	}
}
import java.util.InputMismatchException;
import java.util.Scanner;

public class ExTest {
	// 1. try ~ catch 를 활용한 exception 예외처리. (예외가 발생할만한 곳에 try 처리를 한다.)
	public void doAction() {
		// TODO Auto-generated method stub
		int[] arr = {1, 2, 10, 390, 5, 20, 8, 7};
		Scanner scanner = new Scanner(System.in);
		
		// 1.1 try ~ catch 사용의 올바른 예
		for (int i = 0; i < 99; i++) {
			System.out.println("'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.");
			try {
				int inputNumber = scanner.nextInt();
				scanner.nextLine();		// nextInt return 찌꺼기 소거용.
				System.out.println("입력된 숫자에 해당되는 값은 " + arr[inputNumber]);
			} catch (ArrayIndexOutOfBoundsException e) {	// try에서 발생한 에러가 인덱스를 벗어난 경우를 catch한다. (인덱스 범위가 0~7인데 8이 들어오는 경우)
				System.out.println("인덱스의 범위를 벗어났습니다. 0 ~ 7 사이로 입력해주세요.");
			} catch (InputMismatchException e) {		// try에서 발생한 에러가 데이터 타입이 잘못된 경우를 catch한다. (문자에 숫자가 들어오거나, 숫자에 문자가 들어오는 경우)
				scanner.nextLine();		// int에 잘못 들어와 소거되지 못 하고 무한루프를 발생시키는 문자 찌꺼기 소거용.
				System.out.println("문자를 입력했습니다. 숫자를 입력해주세요.");
			} catch (Exception e) {		// 모든 Exception의 부모형태다. 항상 마지막에는 Exception e로 끝내준다. 이 경우는 위에서 인덱스 범위 초과, 데이터 입 에러를 모두 잡아서 마지막 Exception e는 타지 않는다.
										// 위에서 모든 에러를 잡았더라도 혹시 모를 에러에 대비하기 위해 마지막에 모든 에러의 부모형인 Exception e로 끝내줘야한다.
				// 오류 출력 방법 1. e.printStackTrace()
				e.printStackTrace();	// 프로그램이 죽지는 않고 에러메세지를 출력해준다.
				// 오류 출력 방법 2. System.out.println(e.getMessage())
				System.out.println(e.getMessage() + " 오류 발생");
			}
			System.out.println("------------------------------------");
		}
		
//		// 1.2 try ~ catch 사용의 잘못된 예
//		try {
//			int inputNumber = scanner.nextInt();
//			System.out.println("입력된 숫자에 해당되는 값은 " + arr[inputNumber]);
//		} catch (Exception e) {		// 얘는 위로 올라오면 안 된다. 모든 Exception의 부모이기 때문에 반드시 마지막으로 가야한다.
//			System.out.println("오류 발생");
//		} catch (ArrayIndexOutOfBoundsException e) {
//			System.out.println("인덱스의 범위를 벗어났습니다.");
//		} 
	}
	
	// 2. throws Exception (예외가 발생 시 호출한 곳으로 가져와 처리를 한다.)
	public void doAction2() throws Exception {	// 에러 발생시 호출한 곳으로 보낼거야.
		// TODO Auto-generated method stub
		int[] arr = {1, 2, 10, 390, 5, 20, 8, 7};
		System.out.println("'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.");
		Scanner scanner = new Scanner(System.in);
		
		int inputNumber = scanner.nextInt();	// 여기서는 에러 처리를 하지 않는다. 에러 발생시 호출한 곳으로 에러를 던진다.
		scanner.nextLine();		// nextInt return 찌꺼기 소거용.
		System.out.println("입력된 숫자에 해당되는 값은 " + arr[inputNumber]);
		
	}

}
결과 :

'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
7
입력된 숫자에 해당되는 값은 7
------------------------------------
'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
8
인덱스의 범위를 벗어났습니다. 0 ~ 7 사이로 입력해주세요.
------------------------------------
'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.
a

문자를 입력했습니다. 숫자를 입력해주세요.
------------------------------------
'{1, 2, 10, 390, 5, 20, 8, 7}' 배열이 있습니다. 인덱스를 선택해 주세요.

 

3.2 throws execption에 대한 고찰 execption 강제로 발생시켜 위로 던지기

public class ExecClass {
	public static void main(String[] args) {
		try {
			Test1 test1 = new Test1();
			test1.doAction();
		} catch (Exception e) {
			if (e.getMessage().equals("input 1")) {
				System.out.println("사용자가 1을 입력했습니다.");
			}
		}
	}

}
import java.util.Scanner;

public class Test1 {
	public void doAction() throws Exception {
		Scanner s = new Scanner(System.in);
		int inputNumber = s.nextInt();
		if(inputNumber ==1) {
			throw new Exception("input 1");
			
		}
	}
}

이 예제를 실행해보면 어떤 것인지 감을 잡을 수 있다.

우선 execption은 에러가 발생시 담아내는 공간이다.
그 중에서도 Execption은 모든 예외의 최상단 부모다. (모든 에러를 다 담을 수 있다.)

// 조건이 참인 경우 실행
if (조건) {
	로직
}

// 조건이 에러(execption)인 경우 참이고 그 때 실행
catch (조건) {
	로직
}

if ~ else if ~ else 구문은
try ~ catch ~ catch 구문과 크게 다르지 않다.

A클래스가 B 클래스의 메소드를 실행했다. 그런데 B 클래스의 메소드가 에러가 발생할 경우 B가 죽어버린다. 그래서 B는 try ~ catch로 에러가 나도 죽지 않도록 보호를 한다.

하지만 B가 메소드를 throws Execption으로 정의할 경우 B는 에러를 처리하지도 않고, 에러 발생 시 죽는 대신 호출한 쪽에 에러를 담은 execption을 던져준다. 그러면 A가 그 에러를 받게 되는데, 이 때 A가 에러 처리를 하는 로직이 없다면 죽어버린다. 따라서 A가 에러 처리 하는 로직을 넣어주어 보호를 한다.

즉, try ~ catch와 throws Execption의 차이는 에러가 발생 시 프로그램이 죽는 대신 단지 그것을 잡아내 보호하는 로직을 어디에 오려 붙일거냐의 차이다.

 

위 예제의 경우 B가 Execption에 일부러 값을 넣고 던져 올리니 A는 A가 넣을 값을 가져와 처리하게 되는 것이다. 즉, execption이라는 공간에 값이 있어서 실행한 것이다. 단지 그것 뿐...

 

+ Recent posts