1. 예외 처리 (Exception Handling) 


# 수행 도중 발생하는 예외 상황을 처리할 수 있도록 하는 기능 

* Error Event 


1) 컴파일 에러 (Compile-Time-Error)

(1) 자바 코드로 이루어진 '.java' 파일을 실행 가능한 바이너리 파일인 '.class'로 만드는 과정에서 발생하는 에러 

(2) 소스 파일에 잘못된 구문 오류가 있거나 JVM이 인식할 수 없는 클래스를 사용하여 코딩했을 때 발생한다. 

* Syntax Error


2) 런타임 에러 (Runtime Error)

(1) 컴파일은 되었지만 프로그램 실행 도중(runtime), 논리적인 오류나 외부 요인에 의해 발생하는 에러 

(2) 프로그램 외부의 문제인지 논리적인 오류인지 등 여러 가지 상황을 고려해야 하므로 에러의 원인을 찾아내기 힘든 경우가 있다. 


3) 논리적 에러

(1) 구문 오류나 외부 요인을 제외한 논리적인 오류에 의해 발생하는 에러 

ex. 게임 실행 시 적이 총알을 맞아도 죽지 않는 경우 등 


4) 대표적인 예외 클래스 


(1) NullPointerException: 값이 Null인 상황에서 처리하려 할 때 발생하는 에러

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package exceptionex;
 
public class ExceptionTest02 {
    public static void main(String[] args) {
 
        // 1. 컴파일 에러
        int num;
        // System.out.println(num);
        
        // 2. 런타임 에러 
        String str = null;
        // System.out.println(str.length());
 
    }
}
cs

# 실행 화면 



(2) ArithmeticException: 산술적 에러 (0으로 나누려 할 때)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package exceptionex;
 
import javax.swing.JOptionPane;
 
public class ExceptionTest01 {
    public static void main(String[] args) {
 
        int num1 = Integer.parseInt(JOptionPane.showInputDialog("정수1 입력"));
        int num2 = Integer.parseInt(JOptionPane.showInputDialog("정수2 입력"));
        
        try {
            System.out.println("나눗셈: " + (num1 / num2));
        } catch(ArithmeticException e) {
            System.out.println("0으로 나눌 수 없습니다.");
            e.printStackTrace();
        }
        
        System.out.println("프로그램 종료");
 
    }
}
cs

# num2가 0인 경우 



(3) ArrayIndexOutOfBoundException: 배열의 index 범위를 초과했을 때 발생

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package exceptionex;
 
import javax.swing.JOptionPane;
 
public class ExceptionTest04 {
    public static void main(String[] args) {
 
        int idx = Integer.parseInt(JOptionPane.showInputDialog("배열의 index 입력"));
        int[] arr = { 1234};
 
        try {
            System.out.println(arr[idx]);
        } catch(ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
        } finally {
            System.out.println("예외발생 여부와 무관하게 무조건 실행해야할 코드");
        }
    }
}
cs

# idx가 arr의 길이보다 큰 경우  



(4) FileNotFoundException: 파일 입출력에서 파일이 없을 때 발생 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package exceptionex;
 
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
 
public class ExceptionTest05 {
    public static void main(String[] args) {
 
        // FileReader의 예외처리 의무화!
        FileReader fr = null;
        try {
            fr = new FileReader("Error.java");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {fr.close();} catch (IOException e) {}
        }
    }
}
cs

# 파일이 없는 경우




2. try-catch-finally 구조


# 예외 처리를 하기 위한 가장 기본이 되는 문법


1) try 영역

- 예외가 발생할 수 있는 구문을 지정

- try 영역이 아닌 곳에서 발생된 예외에 대해서는 예외 처리가 불가능하다.


2) catch 영역

- try 영역에서 발생한 예외를 받고, 처리하는 영역

즉, 예외가 발생했을 때 보여줄 코드 

- catch 키워드 다음에 위치한 괄호 내부에는 어떤 예외를 받을지에 대해서 명시한다.

- 괄호 내부에는 변수를 선언하듯 클래스명과 구문을 다룬다. 


3) finally 영역

- 반드시 실행해야 할 구문을 처리하는 구문을 다룬다.

- 예외가 발생 여부와 상관 없이 이 영역 안에 있는 구문들은 반드시 실행한다. 

- try-catch 영역은 반드시 동시에 존재해야 하지만 finally 영역은 상황에 따라서 생략이 가능하다. 



# 예시 (1)



# 설명

예를 들어 야구에 비유하자면, 야구 공(C)을 자바의 '예외(Exception)'이라고 생각할 수 있다. 

예외를 던질 수 있는 투수(B)와 예외를 받을 수 있는 포수(A) 역할을 하는 객체들이 있어야 예외 처리가 가능하기 때문이다. 



# 예시 (2)



# 설명

SampleException2 클래스: 예외를 받아서 처리하는 객체

Integer.toBinaryString() 구문의 Integer 클래스: 예외를 던질 수 있는 객체

NumberFormatException: 숫자의 형식이 잘못된 오류들을 추상화한 클래스, 예외 객체



4) 다중 catch() 구문


(1) try 영역에서 여러 개의 예외들이 발생할 때, 여러 개의 catch() 구문을 사용하여 발생한 예외별로 예외 처리가 가능하다. 

(2) 그러나 예외 처리의 부모 클래스인 Exception 클래스를 사용하면 모든 예외 처리를 한 번에 해결할 수 있다.

* 이때 Exception 클래스는 가장 마지막에 작성해야 한다. 

그렇지 않으면 Exception 클래스 밑에 있는 다른 예외 처리 구문들은 실행하지 않기 때문이다.



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
package exceptionex;
 
import javax.swing.JOptionPane;
 
public class ExceptionTest03 {
    public static void main(String[] args) {
 
        // 변수의 초기화는 try 영역 밖에다가 하는 것이 좋다. 
        int num1 = 0;
        int num2 = 0;
        
        // 사용자가 문자를 입력할 경우, 정수2가 0일 경우: 예외처리 2번 
        try {
            num1 = Integer.parseInt(JOptionPane.showInputDialog("정수1 입력: "));
            num2 = Integer.parseInt(JOptionPane.showInputDialog("정수2 입력: "));
            System.out.println(num1 / num2);
        } catch(NumberFormatException e) {
            System.out.println("숫자를 입력하세요.");
        } catch(Exception e) {
            System.out.println("모든 예외 처리 가능!");
        }
        System.out.println("프로그램 종료");
        
    }
}
cs

# 설명 

- 사용자가 문자를 입력할 경우와 정수2가 0일 경우의 총 예외처리를 2번 하도록 한다.

Line 9~10: 변수의 초기화는 try 영역 밖에다 하는 것이 좋다. 

왜냐면 try 영역은 {} 로 둘러진 블록이기 때문에 try 영역 안에서 초기화한 변수는 영역 밖에서 사용할 수 없기 때문이다.

Line 17: 사용자가 문자를 입력한 경우의 예외 처리

Line 19: 모든 예외 처리로 선언 


# 사용자가 문자를 입력한 경우


# 모든 예외 처리 (정수2가 0인 경우)