[TIL] 예외처리
프로그램에서 발생되는 에러
컴파일에러
- 컴파일할때 발생되는 에러
- 잘못된 문법을 사용하거나 변수를 정의하지 않은 상태에서 사용하는 등 컴파일 단계에서 발생되는 문법적 에러
런타임 에러
프로그램 실행할 때 발생하는 에러로 에러와 예외가 있다.
에러
- 시스템 이상으로 발생되는 에러
- 시스템 레벨의 심각한 오류이므로 시스템에 변화를 주어 문제를 처리하는 경우가 일반적임
- 프로그램 실행 중 에러가 발생하면 프로그램이 종료
예외
- 프로그램 실행 중 발생되는 비정상적인 상황을 의미
- 프로그램 실행 중 예외가 발생하면 프로그램이 종료
논리적 에러
개발자가 문제분석을 잚소하거나 실수에 의해 엉뚱한 결과를 가져오는 에러
예외란?
- 프로그램 실행 중 발생되는 비정상적인 상황을 의미
- 사용자의 잘못된 조작이나 개발자의 잘못된 코딩으로 인한 발생하는 런타임 오류
- 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 클래스를 상속 받아 작성한다.
123456789101112131415161718192021222324252627282930313233package 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 |
댓글