본문 바로가기
Work/Java

[Java] 예외처리 - Exception, Throws, Throw

Exception

프로그램실행중 예기치 못한 사건을 예외라고 한다.

예외 상황을 미리 예측하고 처리할 수 있는데,

이렇게 예외적인 상황을 예측하고 프로그램의 진행을 원활히 해주는 과정을 예외 처리라고 한다.

 

 

아래는 10을 0으로 나누는 메소드 2개를 구현하였다. 

test2는 예외처리 해주고 , test1은 예외처리를 하지않았다.

public class Test {
	private void test1() {
		System.out.println("\n"+"test1  : Start");
		int i=10,j=0;
		System.out.println(i/j);			
		System.out.println("test1  : end");
	}
	
	private void test2() {
		System.out.println("test2  : Start");
		int i=10,j=0;
		try {
			System.out.println(i/j);			
		}
		catch(Exception e){
			System.out.println(e);
		}

		System.out.println("test2  : end");
	}

	public static void main(String[] args) {
		Test t = new Test();
		t.test2();
		
		t.test1();
	}
}

 

test2를 먼저 실행하고 , test1을 실행해보았더니,

역시나 test2는 정상적으로 끝까지 잘 수행되었지만,

test1은 예외처리를 해주지않았기 때문에, 프로그램이 종료되어 마지막줄이 출력되지 않았다.

 

프로그램을 짤때는 항상 이렇게 예외처리와 에러에 대한 로깅이 필요하다.

 

Throw 와 Thorws

위에서는 예외처리를 구현된 메소드 내에서 해주었는데,

사실 위와같은 코드는 올바른 예외처리 Case가 아니다.

메소드별로 밀접한 관계를 가지는 경우, 선행 메소드가 에러시 후행 메소드는 실행이 중지되야하는 경우가 있다.

예를 들어.

상품발송의 트렌젝션에 포장, 영수증 발생, 발송이 순차적으로 이루어 질때,

아래와 같이 짜여지면, 포장중 에러발생시, 발송까지 이어지지 않는다.

상품발송() {
    try {
        포장();
        영수증발행();
        발송();
    }catch(예외) {
       모두취소();
    }
}

포장() throws 예외 {
   ...
}

영수증발행() throws 예외 {
   ...
}

발송() throws 예외 {
   ...
}

하지만 아래와 같이

각각의 메소드에 예외처리가 된다면,

상품발송() {
    포장();
    영수증발행();
    발송();
}

포장(){
    try {
       ...
    }catch(예외) {
       포장취소();
    }
}

영수증발행() {
    try {
       ...
    }catch(예외) {
       영수증발행취소();
    }
}

발송() {
    try {
       ...
    }catch(예외) {
       발송취소();
    }
}

포장은 되지않고 영수증은 발행되어 발송되버리는 뒤죽박중의 상황이 연출되는것이다.

트렌젝션 관리를 잘하기 위해서는, 예외처리가 그만큼 중요하다. 

 

 

 

메소드 별로 짜는것보다, 메서드에서 던져주도록 짜고, 호출하는 부분에서 Try-Catch를 짜는것이 올바른 것이다.

 

throws 문을 사용하면 Exception을 호출하는 상위클래스에 전달해준다.

throw 문을 이용하면 Exception문을 사용자가 정의할 수 있다.

상속받을수 있는 Exception 클래스는 두 가지가 있다.

  1. RuntimeException
  2. Exception

 

 

RuntimeException은 실행 시 발생하는 예외이고

Exception은 컴파일 시 발생하는 예외이다.

 

즉, Exception은 프로그램 작성 시 이미 예측가능한 예외를 작성할 때 사용하고

RuntimeException은 발생 할 수도, 발생 안 할 수도 있는 경우에 작성한다.

 

 

 1. 컴파일시 에러를 호출하는 익셉션처리

 

package Exception;

public class Test {
	// 컴파일시 에러 발생시키는 Exception 클래스를 가지고 익셉션 생성
	public class FoolException extends Exception {
	}
    
	private void test1() throws FoolException{
		System.out.println("\n"+"test1  : Start");
		int i=10,j=0;
		if(j == 0){
		    throw new IllegalArgumentException("0으로 나눌 수 없어요.");
		}
		System.out.println(i/j);			
		System.out.println("test1  : end");
	}
	

	public static void main(String[] args) {
		Test t = new Test();
		System.out.println("--- main : Start --- ");
		try {	
			t.test1();
		}catch(Exception e) 
			System.out.println("--- main Exception : "+ e);
		}
		System.out.println("--- main : End --- ");
	}
}

 

 

2. 실행중 에러발생시 Exception처리

 

package Exception;

public class Test {
	// 컴파일시 에러 발생시키는 Exception 클래스를 가지고 익셉션 생성
	public class FoolException extends RuntimeException {
	}
    
	private void test1() throws FoolException{
		System.out.println("\n"+"test1  : Start");
		int i=10,j=0;
		if(j == 0){
		    throw new IllegalArgumentException("0으로 나눌 수 없어요.");
		}
		System.out.println(i/j);			
		System.out.println("test1  : end");
	}
	

	public static void main(String[] args) {
		Test t = new Test();
		System.out.println("--- main : Start --- ");
		try {	
			t.test1();
		}catch(Exception e) 
			System.out.println("--- main Exception : "+ e);
		}
		System.out.println("--- main : End --- ");
	}
}

 

 

 

https://wikidocs.net/229

https://programmers.co.kr/learn/courses/9