본문 바로가기
Back-End/Java

[Java] 예외(Exception) 처리

by 찐코딩 2021. 8. 18.

에러(error)

  - 하드웨어의 오동작 또는 고장으로 인한 오류.
  - 에러가 발생하면 프로그램 종료.
  - 정상 실행 상태로 돌아갈 수 없음.

 예외(exception)

  - 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인한 오류.
  - 예외가 발생하면 프로그램 종료.
  - 예외 처리를 추가해 주면 정상 실행 상태로 돌아갈 수 있음.
  - 프로그램을 위한 보험 처리. 위험한 상황에서 다른 코드를 보호하는 장치.

 예외의 종류

  1. 일반(컴파일) 예외
     - 예외 처리 코드가 없다면 컴파일이 되지 않는 예외.
  2. 실행 예외
     - 예외 처리 코드를 생략하더라도 컴파일이 되는 예외.
       즉, 컴파일 하는 과정에서 예외 처리 코드를 검사하지 않는 예외를 말함.
     - 경험에 따라 예외 처리 코드를 작성할 필요가 있음.

 예외 처리의 목적

  - 프로그램을 실행 시 발생할 수 있는 상황들을 미리 정해 놓고,

예외가 발생했을 경우에 대비하는 코드를 작성하여 프로그램이 정상적으로 작동하도록 하기 위함.

 예외 처리

  - 실행 시간에서 발생한 예외(오류)를 프로그램으로 처리한다는 의미.
  - 관련된 키워드
   1. try ~ catch ~ finally 블럭  
    2. throws 키워드


1. try ~ catch ~ finally 블럭

형식)

try {
      // 예외가 발생할 가능성이 있는 코드;
} catch (예외클래스 참조변수) {
    // 예외가 발생 시 실행되는 내용.
    // 참조변수 : 예외 정보를 넘겨 받는 변수.
    // 보통 catch (Exception1 e1) 이런식으로 작성한다
} finally {
     // 생략도 가능함.
     // 예외와 상관없이 실행되는 코드;
}

★ try블럭에서 예외가 발생하면, 예외가 발생한 위치 이후에 있는 try 블럭의 문장들은 수행되지 않음

ex)

package sist;

public class Ex11 {

	public static void main(String[] args) {
		try {
			System.out.println(1);
			System.out.println(2);
			System.out.println(3/0);
			System.out.println(4);
			System.out.println(5);
		} catch (Exception e) {
			System.out.println(6);
		}
		System.out.println(7);
	}
}

결과

1
2
6
7

try블럭 중 3번째 문장(System.out.println(3/0);)에서 정수를 0으로 나누려는 시도가 있었기에 예외가 발생하여

이후 try블럭 문장들(System.out.println(4); System.out.println(5);)는 시행되지 않고

catch문과 try블럭 밖의 문장이 시행되었다.

 

 1-2. 다중 catch문

try {
      // 예외가 발생할 가능성이 있는 코드;
} catch (Exception1 e1) {
    // Exception1 발생 시, 이를 처리하기 위한 코드;
} catch (Exception2 e2) {
    // Exception2 발생 시, 이를 처리하기 위한 코드;    
} catch (ExceptionN eN) {
    // ExceptionN 발생 시, 이를 처리하기 위한 코드;
} finally {
     // 생략도 가능함.
     // 예외와 상관없이 실행되는 코드;
}
하나의 try블럭 다음에는 여러 종류의 예외를 처리할 수 있도록
하나 이상의 catch블럭이 올 수 있으며, 
이 중 발생한 예외의 종류와 일치하는 단 한개의 catch블럭만 수행
발생한 예외의 종류와 일치하는 catch블럭이 없으면 예외는 처리되지 않는다

 

  - catch문을 여러 개 사용하여 예외를 처리하는 방식.
  - catch문은 순차적으로 위에서 아래로 실행이 됨.
  - 주의) 예외를 처리하는 가장 상위의 Exception 클래스는 맨 마지막 줄에 나와야 한다.
         (만약 첫 문장에 나올 경우 error 발생)

 

2. throws 키워드

  - 예외 처리를 위임시키는 명령어.
    형식)

메서드명 throws 예외처리클래스 {    }

  - throws로 지정된 메서드를 호출할 경우 메서드 내에서 예외가 발생이 되면

해당 예외를 메서드를 호출한 곳으로 위임시켜서 예외를 처리하는 방법.

 

 

printStackTrace()

- 에러 메세지의 발생 근원을 찾아서 단계별로 에러를 출력해주는 메소드

 

 


예제01)

try ~ catch 문 예제

package sist;

public class Ex04 {

	public static void main(String[] args) {
	
		System.out.println("프로그램 시작");
		
		int num1 = 10, num2 = 0, result = 0;
		
		try  {
			result = num1 / num2; 	// 0으로 나눈 경우
		} catch (Exception e) {
			System.out.println("0으로 나눈 예외 발생");
			System.out.println("예외 정보 : " + e);
		}
		
		System.out.println("result : " + result);
		
		System.out.println("프로그램 종료");

	}

}

결과

프로그램 시작
0으로 나눈 예외 발생
예외 정보 : java.lang.ArithmeticException: / by zero
result : 0
프로그램 종료

정수는 0으로 나눌 수 없기에 java.lang.ArithmeticException와 같은 에외가 발생.

* ArithmeticException : 산술연산과정에서 오류가 있을 때 발생하는 예외

 

public class Ex05 {

	public static void main(String[] args) {
		
		System.out.println("프로그램 시작");
		
		String str1 = "korea", str2 = null;
		
		try {
			System.out.println("str1 문자열 길이 : " + str1.length());
			System.out.println("str2 문자열 길이 : " + str2.length());
		} catch(Exception e) {
			System.out.println("예외정보 >>> " + e);
		}
		
		System.out.println("프로그램 종료");
	}
}

결과

프로그램 시작
str1 문자열 길이 : 5
예외정보 >>> java.lang.NullPointerException
프로그램 종료

사용 하려는 객체를 정의한 뒤, 생성자를 이용해 생성(인스턴스 생성)하지 않고 그 객체를 사용 하려고 했기 때문에 발생하는 예외

 

try~catch문을 사용하여 100을 0~9까지의 임의의 수로 나눠보자.

package sist;

public class Ex10 {

	public static void main(String[] args) {
		
		int number = 100;
		int result = 0;
		
		for(int i=0; i<10; i++) {
			try {	// 예외가 발생할 구문 작성
				// number(100)을 0~9 사이의 임의의 정수로 나눈 결과
				result = number / (int)(Math.random()*10);
				System.out.println(result);
			} catch(Exception e) {
				System.out.println("0");
			}
		}

	}

}

결과

33
20
14
33
33
100
25
25
0     → 예외가 발생해서 0이 출력됨
100

랜덤 숫자중 0으로 나누려는 시도가 있었기에 ArithmeticException 예외가 발생하여 catch문을 통해 0이 출력됨

만일 예외처리 하지 않았다면, 8번째 줄까지만 출력되고 9번째 줄에서 예외가 발생해서 프로그램이 비정상적으로 종료되었을 것이다.

 


예제02)

다중 catch문 예제

package sist;

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

public class Ex07 {

	public static void main(String[] args) {
		
		System.out.println("프로그램 시작");
		
		Scanner sc = new Scanner(System.in);
		
		int num = 0;		
		String str = "";		
		int[] arr = {10, 20, 30, 40, 50};
		
		try {		
        	// 예외가 발생할 가능성이 있는 코드 삽입
            System.out.print("키보드로 부터 정수를 입력 받습니다. >>> ");
			num = sc.nextInt();
			System.out.println("str 문자열의 길이 : " + str.length());
			arr[5] = 100;
            
          // InputMismatchException 혹은 하위 예외 발생 시 처리
		} catch(InputMismatchException e) {
			System.out.println("타입 불일치 예외 발생");
			System.out.println("예외 정보 : " + e);
            
            // InputMismatchException 혹은 하위 예외 발생 시 처리
		} catch(NullPointerException e) { 
			System.out.println("Null 값을 가지는 예외 발생");
			System.out.println("예외 정보 : " + e);
            
            // 모르는 예외 발생 시 처리, 최상위 예외 클래스
		} catch(Exception e) { 
			System.out.println("모르는 예외 발생");
			System.out.println("예외 정보 : " + e);
            
		} finally {
			sc.close();
		}
		
		System.out.println("프로그램 종료");
		

	}

}

결과

 

1) 키보드로 정수를 입력할 경우

프로그램 시작
키보드로 부터 정수를 입력 받습니다. >>> 2
str 문자열의 길이 : 0
모르는 예외 발생
예외 정보 : java.lang.ArrayIndexOutOfBoundsException: 5
프로그램 종료

인덱스가 배열의 크기보다 크거나 음수 인덱스에 대한 요청이 있으면 자바는 위의 예외를 발생

 

2) 키보드로 정수가 아닌 값을 입력할 경우

프로그램 시작
키보드로 부터 숫자를 입력 받습니다. >>> 가
타입 불일치 예외 발생
예외 정보 : java.util.InputMismatchException
프로그램 종료

 

예제03) printStackTrace() 예문

package sist;

public class Ex08 {

	void exception1() {
		String str1 = "java";
		String str2 = null;
		
		try {
			System.out.println("str1문자열의 길이 : " + str1.length());
			System.out.println("str2문자열의 길이 : " + str2.length()); }
			
		/*
		 * printStackTrace()
		 * - 에러 메세지의 발생 근원을 찾아서
		 *   단계별로 에러를 출력해 주는 메서드.
		 */	
		catch(Exception e) {
			e.printStackTrace(); }
		
	}
	
	void exception2() {
		
		int num1 = 15, num2 = 0, result = 0;
		
		try {
			result = num1/num2;
		}catch(Exception e) {
			e.printStackTrace();
		}

	}
	
	public static void main(String[] args) {
		
		Ex08 ex08 = new Ex08();
		
		ex08.exception1();
		ex08.exception2();
	}
}

결과

str1문자열의 길이 : 4
java.lang.NullPointerException
	at sist.Ex08.exception1(Ex08.java:11)
	at sist.Ex08.main(Ex08.java:39)
java.lang.ArithmeticException: / by zero
	at sist.Ex08.exception2(Ex08.java:28)
	at sist.Ex08.main(Ex08.java:40)

java.lang.NullPointerException 라는 예외가

at sist.Ex08.exception1(Ex08.java:11)와 at sist.Ex08.main(Ex08.java:39)에서 발생

(※ java.lang.NullPointerException : 사용 하려는 객체를 정의한 뒤, 생성자를 이용해 생성(인스턴스 생성)하지 않고 그 객체를 사용 하려고 했기 때문에 발생하는 예외)

 

java.lang.ArithmeticException라는예외가

at sist.Ex08.exception2(Ex08.java:28)와 at sist.Ex08.main(Ex08.java:40)에서 발생

(※ java.lang.ArithmeticException : 산술 연산과정에서 오류가 있을 때 발생하는 예외, 정수는 0으로 나눌 수 없으므로 해당  예외 발생)

 

 

예제04) throws 키워드 예문

public class Ex09 {
	
	void exception1() throws Exception {
		String str1 = "java";
		String str2 = null;
			
		System.out.println("str1문자열의 길이 : " + str1.length());
		System.out.println("str2문자열의 길이 : " + str2.length());
		
		}
		
	void exception2() throws Exception {
			
		int num1 = 15, num2 = 0, result = 0;
			
		result = num1/num2;

	}
		
		public static void main(String[] args) {
			
			Ex09 ex09 = new Ex09();
			
			try {
				ex09.exception1();
				ex09.exception2();
			}catch (Exception e) {
            	// printStackTrace() : 에러 메세지의 발생 근원을 찾아서 단계별로 에러를 출력해 주는 메서드.
				e.printStackTrace();
			}	
		}
}

  - exception1, 2 모두 throws로 지정되었으므로, main메서드에서 이들 메서드를 호출할 경우

메서드 내에서 예외가 발생이 되면, 해당 예외를 메서드를 호출한 곳으로 위임시켜서 예외를 처리

 

 

결과

str1문자열의 길이 : 4
java.lang.NullPointerException
	at sist.Ex09.exception1(Ex09.java:10)
	at sist.Ex09.main(Ex09.java:27)

 

댓글