Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Tags
more
Archives
Today
Total
관리 메뉴

forDevLife

[생활코딩-자바입문] 핵심 요약 2 본문

Java

[생활코딩-자바입문] 핵심 요약 2

JH_Lucid 2020. 11. 8. 18:40

생활코딩 37. 예외

 

1) 예외란 무엇인가?

- 참고로, println : 줄바꿔서 출력 / print : 서식없을 때 string만 출력 / printf : c, c++과 동일하게 서식 있을 때 출력(서식 : %d 이런거)

 

- 아래 코드에서, try 부분에 예외가 발생할지도 모르는 부분을 작성한다. 예외(에러)가 발생되면, catch 블록에 들어있는 구문이 실행.

 

- catch 부분의 catch (Exception e)는 마치 메소드 처럼 생겼다. 일종의 메소드라고 생각해도 괜찮을 듯? 자바 가상머신이 프로그램을 실행하는 과정에서, try 블록에서 에러가 발생하면 catch 구문을 찾는다. 이 구문의 매개변수로 에러 정보가 담긴 객체를 매개변수로 전달한다. 그 객체의 데이터 타입은 Exception 클래스이다. 

다시 말해서, 에러 상황에 대한 정보가 담긴 객체를 catch의 인자로 전달한다. 그럼 catch 안에서는 자바가 전달한 문제 상황을 Exception 객체를 이용하여 뒷수습을 하게 된다.

public void divide() {
	try {
		System.out.print("계산 결과는 ");
		System.out.print(this.left / this.right);
		System.out.print(" 입니다.");
	} catch (Exception e) {
		System.out.println("오류가 발생했습니다 :" +e.getMessage());
	}
}

위의 예외 출력 결과

 

2) 뒷수습

public void divide() {
	try {
		System.out.print("계산 결과는 ");
		System.out.print(this.left / this.right);
		System.out.print(" 입니다.");
	} catch (Exception e) {
		//System.out.println("오류가 발생했습니다 :" +e.getMessage());
		System.out.println("\n\ne.getMessage()\n"+e.getMessage());
		System.out.println("\n\ne.toString()\n"+e.toString());
		System.out.println("\n\ne.printStackTrace()");
		e.printStackTrace();
	}
}

출력 결과 참조

- getMessage( ) : 예외 상황에 대한 가장 간단한 힌트가 들어있는 부분

- toString( ) : 예외 상황 + 어떤 형태의 exception이 발생했는지에 대한 부분 추가

- printStackTrace( ) : 위에꺼 모두 포함 + 에러 코드 위치, 얘는 에러메세지 문자열을 반환하는게 아닌, 내부적으로 화면에 에러 상황 출력

 

 

추가로, try - catch block 밖에 작성되어있는 부분은 예외처리 이후에 실행됨을 유의 한다. 아래 참고해라.

public void divide() {
	try {
		System.out.print("계산 결과는 ");
		System.out.print(this.left / this.right);
		System.out.print(" 입니다.");
	} catch (Exception e) {
		System.out.println("\n\ne.getMessage()\n"+e.getMessage());
	}
	System.out.println("divide end"); // 예외처리 이후, 이 부분 실행된다.
}

 

3) 다양한 예외와 다중 캐치

a.z(10, 1)은 out of index 에러이고, a.z(1, 0)은 0으로 나눠서 발생하는 에러이다. 아래와 같이 catch 내의 printStackTrace를 통해 두 에러가 각각 처리된다. 만약, 예외에 따라서 처리를 다르게 하고 싶다면? 아래에서 다시 설명하겠다.

package org.opentutorials.exception;

class A {
	private int[] arr = new int[3];
	
	A() {
		arr[0] = 0;
		arr[1] = 10;
		arr[2] = 20;
	}
	public void z(int first, int second) {
		try {
			System.out.println(arr[first] / arr[second]);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
public class ExceptionDemo1 {

	public static void main(String[] args) {
		A a = new A();
		a.z(10, 1);
		a.z(1, 0);
	}
}

 

 

아래는, 각 예외마다 다르게 처리하고 싶을때의 경우이다. 각 catch는 else if와 같은 역할을 하지만, 이름은 모두 동일하다.

마지막의 경우, 여태 했던 방식과 동일한데 내가 지정한 에러 이외의 에러를 처리하기 위함이다.

class A {
	private int[] arr = new int[3];
	
	A() {
		arr[0] = 0;
		arr[1] = 10;
		arr[2] = 20;
	}
	public void z(int first, int second) {
		try {
			System.out.println(arr[first] / arr[second]);
		} catch (ArrayIndexOutOfBoundsException e) { // else if 역할
			System.out.println("array bound exception");
		} catch (ArithmeticException e) { // else if 역할
			System.out.println("arithmetic exception");
		} catch (Exception e) { // else 역할
			System.out.println("exception");
		}
	}
}
public class ExceptionDemo1 {

	public static void main(String[] args) {
		A a = new A();
		a.z(10, 1);
		a.z(1, 0);
		a.z(2, 1);
	}
}

 

 

아래의 경우, 포괄하는 예외인 Exception e를 맨 위에 올렸다. 이렇게 될 경우, 모든 예외가 여기에서만 처리되므로 특정 상황 예외는 실행될 기회를 얻을 수 없게 된다. 따라서 자바 컴파일러가 이 부분에 대한 에러를 준다. 참 친절한 것 같다.

빨간 줄로 에러를 표시해주는 자바 컴파일러

 

4) Finally

finally 예외 처리 요소에 대해서 알아보자. 이 절은 try / catch와 함께 올 수 있으며, 언제나 try / catch 뒤에 나와야 하고, 다른 위치에서 등장하면 문법 오류가 발생한다. finally 부분은 try / catch 문의 결과와는 무관하게 언제나 실행되도록 약속된 로직이다.

 

아래 코드를 보면, finally 부분은 예외가 어떻게 실행되든(즉 정상 혹은 에러가 나든) 항상 출력된다. 데이터베이스 예시로 들면, 작업을 정상적으로 끝내거나 예외가 발생했을때는 동일하게 application과 db 간의 연결을 끊어줘야 된다. 다른 application도 db와 연결을 해야하는데 계속 잡고 있으면 문제가 되기 때문이다. 따라서 finally를 통해 연결 끊는 부분을 작성해주면, 정상이든 비정상이든 연결을 종료시킬 수 있다.

 

+ 추가로, try / catch 이후에 작성할 경우, 앞에서 봤듯이 정상적으로 동작했음을 보였다. finally와 다른점은, try / catch 내의 처리과정에서 return이 있을 경우 해당 부분은 처리가 되지 않는다. 이게 finally와의 차이점 같다.

package org.opentutorials.exception;

class A {
	private int[] arr = new int[3];
	
	A() {
		arr[0] = 0;
		arr[1] = 10;
		arr[2] = 20;
	}
	public void z(int first, int second) {
		try {
			System.out.println(arr[first] / arr[second]);
		} catch (ArrayIndexOutOfBoundsException e) { // else if 역할
			System.out.println("array bound exception");
		} catch (ArithmeticException e) { // else if 역할
			System.out.println("arithmetic exception");
		} catch (Exception e) { // else 역할
			System.out.println("exception");
		} finally {
			System.out.println("finally");
		}
        // 이 부분에 작성된 코드는, 만약 위의 처리과정에 return이 있다면 해당 부분이 실행되지 않을 것이다. 
	}
}
public class ExceptionDemo1 {

	public static void main(String[] args) {
		A a = new A();
		a.z(10, 1);
		a.z(1, 0);
		a.z(2, 1);
	}
}

 

Comments