본문 바로가기

[TIL] 예외처리

인포꿀팁 발행일 : 2020-08-12

프로그램에서 발생되는 에러

컴파일에러

  • 컴파일할때 발생되는 에러
  • 잘못된 문법을 사용하거나 변수를 정의하지 않은 상태에서 사용하는 등 컴파일 단계에서 발생되는 문법적 에러

 

런타임 에러

프로그램 실행할 때 발생하는 에러로 에러와 예외가 있다.

에러

  • 시스템 이상으로 발생되는 에러
  • 시스템 레벨의 심각한 오류이므로 시스템에 변화를 주어 문제를 처리하는 경우가 일반적임
  • 프로그램 실행 중 에러가 발생하면 프로그램이 종료

예외

  • 프로그램 실행 중 발생되는 비정상적인 상황을 의미
  • 프로그램 실행 중 예외가 발생하면 프로그램이 종료

논리적 에러

개발자가 문제분석을 잚소하거나 실수에 의해 엉뚱한 결과를 가져오는 에러


 

예외란?

  • 프로그램 실행 중 발생되는 비정상적인 상황을 의미
  • 사용자의 잘못된 조작이나 개발자의 잘못된 코딩으로 인한 발생하는 런타임 오류
  • 0으로 나누거나 배열의 첨자를 벗어나는 경우 또는 존재하지 않는 파일을 오픈하여 읽어 들이는 것등
  • 프로그램 실행 중 예외가 발생하면 프로그램이 종료

 

예외처리 Exception Handling

  • 프로그램 실행 시 발생될 수 있는 예외에 대비하기 위한코드를 작성하는 것
  • 예외처리를 통하여 프로그램의 비정상 종료를 막고 정상적인 실행 상태를 유지한다.

 

예외의 종류

checked exception

  • 컴파일 할때 컴파일러에 의해 체크되는 예외
  • 프로그램 작성시 예외처리를 명시적으로 하지 않으면 컴파일 오류 발생
  • java.lang.Exception과 Exception을 상속받은 예외 클래스 중 RuntimeException을 제외한 클래스

 

unchecked exception

  • 컴파일 할때 체크되지 않으며 런타임시 발생되는 예외
  • java.lang.RuntimeException과 RuntimeException 을 상속받은 클래스
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package ex0812;
 
public class Exception_Ex2 {
    public static void main(String[] args) {
        int a= 20;
        int b=0;
        int c;
        
        try {
            //예외가 발생할 가능성이 있는 코드
            c=a/b;
            System.out.println("결과: "+c);
        } catch (ArithmeticException e) {
            //ArithmeticException : 연산이 불가능할때 발생 . 예를 들어 0으로 나눌때
            //런타임시 발생하는 unchecked exception이라고 함
            //예외가 발생할 때 실행할 코드
            System.out.println("수를 0으로 나눌수 없다.");
        }
        System.out.println("종료...");
    }
}
 
cs

예외 클래스

java.lang.Throwable 클래스

  • 자바의 모든 에러와 예외의 super 클래스

주요 메소드

java.lang.Exception 클래스

  • Throwable 클래스를 상속 받은 하위 클래스
  • Exception 클래스나 Exception 클래스를 상속 받은 하위 클래스는 RuntimeException 클래스를 제외하고 모두 컴파일할 때 예외를 체크하는 checked exception 이다.
  • 프로그램을 작성 시 명시적으로 예외처리를 하지 않으면 컴파일 오류 발생
  • exception 클래스를 상속받은 주요 checked exception


예외 처리

장점:

  • 예외 발생시 비정상적인 프로그램 종료를 막고 프로그램 실행 상태를 유지한다.
  • 프로그램의 실행 코드와 에러를 처리하는 코드를 분류 할 수 있다.
  • 메소드의 콜 스택에 에러를 차례대로 보낼 수 있다.
  • 예외 타입을 종류별로 분류할 수 있다.

try~catch에 의한 예외 처리

try 문으로 영역이 지정된 문에서 예외 상황이 발생하면, 해당 예외를 처리하는 catch 문 쪽으로 넘겨 오류에 관한 예외 상황을 처리한다.

1) try 블록

  • 예외를 감시하고자 하는 문장들을 try블록 내에 기술한다.
  • 예외가 발생할 경우 try블록내의 문자 실행을 중지하고 해당 예외의 catch블록의 내용을 실행한다.

 

2)catch 블록

  • 예외가 발생할 경우 처리할 문장을 기술
  • catch문은 Throwable 클래스를 상속받는 예외클래스 타입을 가진 한 개의 인자를 갖는다.
  • catch 블록은 여러 개가 올 수 있다.
  • 예외가 try블록에서 발생하면 catch블록을 순차적으로 찾아 내려가면서 해당 예외를처리하는 예외클래스의 인자를 가진 catch블록의 문장을 수행한다.
  • 여러개의 catch문이 존재할 경우 순차적으로 예외를 찾기 때문에 catch의 예외 클래스들은 자세한 예외를 나타내는 하위 클래스를 앞에두고 범위가 넓은 예외를 나타내느 상위클래스를 나중에 두어야한다.

finally 블록

  • 런타임시 예외 발생 여부와 상관없이 반드시 실행 해야할 코드를 finally블록에 기술한다.
  • 예외가 발생하면 해당 예외를 처리하는 catch블록을 실행한 후 finally 블록이 실행되고 예외가 발생하지 않았을 경우, break, continue, return 과 같은 문장을 통해서 블록을 빶버나갈 경우에도 실행되며 system.exit(0); 문장이 있는 경우에만 finally 절을 수행하지 않고 프로그램이 종료된다.
  •  

 

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
package ex0812;
 
public class Finally_Ex1 {
    public static void main(String[] args) {
        
    }
}
class User9{
    public int sum(String num) {
        int s=0;
        try {
            int n = Integer.parseInt(num);
            if(n<0) {
                return -1;
            }
            for(int i =1 ; i<=n; i++) {
                s+=i;
            }
        } catch (NumberFormatException e) {
            System.out.println("숫자가 아닙니다.");
        }finally {
            //System.exit(0); 일때만 실행되지 않음
            System.out.println("return을 해도 실행됨");
        }
        return s;
    }
}
cs

메소드의 throws에 예외 명시

  • 메소드 내부에서 예외가 발생할 경우 try-catch 블록으로 예외 처리를 하지만 호출한 곳으로 throws를 사용해서 예외를 넘길 수도 있다.
  • 호출한 메소드에서 예외를 처리해야하는 경우 사용한다.

throw

  • 메소드에서 특정 조건에 따라 throw를 이용하여 예외를 명시적으로 발생 시킨다.
  • throw에 의해 발생되는 예외가 RuntimeException 과 RuntimeException의 하위클래스가 아닌 메소드의 시그니처에서 throws 하거나 try - catch하거나 try-catch에서 해당 예외를 catch해야한다.
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
31
32
33
34
35
36
37
38
39
40
package ex0812;
 
public class ThrowsException_Ex6 {
    public static void main(String[] args) {
        User16 obj = new User16();
        
        try {
            obj.set(-5);
            int n = obj.getValue();
            System.out.println(n);
        } catch (Exception e) {
            System.out.println("main : "+e.getMessage());
        }
    }
}
class User16 {
    private int value;
 
    public int getValue() {
        return value;
    }
 
    public void setValue(int value) throws Exception {
        //예외를 건네준다.
        if(value < 0) {
            throw new Exception("0이상만 가능합니다.");
        }
        this.value = value;
    }
    public void set(int value) throws Exception {
        // 예외를 건내준다.
        //예외를 건내주지 않으면 main에서 예외가 발생되지 않는다.
        try {
            setValue(value);
        } catch (Exception e) {
            throw e; // 예외를 다시 던진다.
//            System.out.println(e.getMessage());
        }
    }
}
cs

사용자 정의 예외 작성

    • 사용자에 의해 만들어지는 예외
    • 사용자 정의 checked 예외 클래스 작성
      • Exception 클래스를 상속받아 작성한다.
    • 사용자 정의 unchecked 예외 클래스 작성
        • RuntimeException 클래스를 상속 받아 작성한다.
      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
      31
      32
      33
      package ex0812;
       
      public class Ex13 {
          public static void main(String[] args) {
              
          }
      }
      //사용자 정의 예외 클래스 만들기(checked exception)
      class MyException extends Exception{
          /**
           * 
           */
          private static final long serialVersionUID = 1L;
          // 네트워크 전송시 객체를 구분하기 위한 상수값
          
          public MyException(String message) {
              super(message);
          }
      }
       
      class User18{
          public int sum(int n) throws MyException {
              int s = 0;
              
              if(n<0) {
                  throw new MyException("0이상이만 가능");
              }
              for(int i =1;i<=s;i++) {
                  s+=i;
              }
              return s;
          }
      }
      cs

       

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package ex0812;
 
import java.util.InputMismatchException;
import java.util.Scanner;
 
public class CalcEx1 {
    public static void main(String[] args) {
        Calc cal = new Calc();
        cal.calculate();
    }
}
class OperatorValidException extends Exception{
 
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    
    public OperatorValidException(String message) {
        super(message);
    }
}
 
class ArithmeticValidException extends Exception{
 
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String message;
    public ArithmeticValidException(String message) {
        super(message);
        this.message = message;
    }
    @Override
    public String toString() {
        return "ArithmeticValidException:"+message;
    }
    
}
 
class Calc {
    private Scanner sc = new Scanner(System.in);
 
    public void calculate() {
        int n1, n2;
        char oper;
        try {
            System.out.print("첫번째 수?");
            n1 = inputNumber();
 
            System.out.print("두번째 수?");
            n2 = inputNumber();
 
            System.out.print("연산자");
            oper = inputOperator();
            String s = result(n1, n2, oper);
            System.out.println(s);
        } catch (InputMismatchException e) {
            System.out.println("숫자만 입력 가능합니다.");
        } catch (OperatorValidException e) {
            System.out.println("연산자 입력이 잘못되었습니다.");
        } catch (ArithmeticValidException e) {
            System.out.println(e.toString());
        }catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
 
    private int inputNumber() {
        int n;
        try {
            n = sc.nextInt();
        } catch (InputMismatchException e) {
            throw e;
        }
        return n;
    }
 
    private char inputOperator() throws OperatorValidException {
        char ch = '\0';
        ch = sc.next().charAt(0);
 
//        if(ch!='+'&&ch!='-'&&ch!='*'&&ch!='/') {
//            new Exception("연산자 입력 오류");
//        }
        String s = Character.toString(ch);
        // s.matches("패턴") => 문자열 s가 패턴에 일치하면 true
        if (!s.matches("(\\+|\\-|\\*|\\/)")) {
            throw new OperatorValidException("연산자 입력 오류");
        }
 
        return ch;
    }
 
    private String result(int n1, int n2, char ch) throws ArithmeticValidException {
        String s = null;
        if (ch == '/' && n2 == 0) {
            throw new ArithmeticValidException("0으로 나누면 안된다.");
        }
        switch (ch) {
        case '+':
            s = String.format("%d+%d=%d", n1, n2, n1 + n2);
            break;
        case '-':
            s = String.format("%d+%d=%d", n1, n2, n1 - n2);
            break;
        case '*':
            s = String.format("%d+%d=%d", n1, n2, n1 * n2);
            break;
        case '/':
            s = String.format("%d+%d=%d", n1, n2, n1 / n2);
            break;
        }
        return s;
    }
 
}
cs

'Language > JAVA' 카테고리의 다른 글

[TIL] 컬렉션 프레임워크  (0) 2020.08.14
[TIL] 제네릭  (2) 2020.08.12
[TIL] 중첩 클래스  (0) 2020.08.11
[TIL] 인터페이스  (0) 2020.08.11
[TIL] 추상 클래스  (0) 2020.08.10

댓글