예외를 왜 사용해야 하는가?
- 전통적인 절차적 오류 처리는 사용하는 번거로움
- 오류 처리를 위한 코드에서 오류를 일으킬 수 있음
- 오류가 의미를 포함하지 않음
예외 객체
- Checked exception
- 체크 예외가 발생할 수 있는 메소드를 사용할 경우 복구가 가능한 예외로, 반드시 예외 처리를 해야함
- Unchecked exception
- 명시적으로 예외 처리를 강제하지 않음
- Error
- 메모리 부족 등 시스템에 심각한 상황이 발생했을 경우
try/catch 블록
1
2
3
4
5
6
7
8
public class Hello {
public static void main(String[] args) {
String s = args[0];
int i = Integer.parseInt(args[1]);
System.out.println(s+i);
}
}
위와 같이 작성했을때 만약 사용자가 아무값도 입력하지 않는다면 오류가 발생할 것이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Hello {
public static void main(String[] args) {
try{
String s = args[0];
int i = Integer.parseInt(args[1]);
System.out.println(s+i);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("please input data");
}catch(NumberFormatException e){
System.out.println("please input int type");
}
}
}
Exception 하나로 처리하여도 되지만 사용자에게 정확한 오류를 알리기 위해 각각 catch하여 오류 메세지를 사용자에게 보여줄수 있다.
throw 문
- 상황에 맞는 적절한 예외를 발생시킴
- 예외에 의미 있는 메시지를 제공
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import java.time.DateTimeException; //1시간 까지 측정할 수 있는 타임스톱 public class throwTest { public static void main(String[] args) { int minute=0; try { minute = Integer.parseInt(args[0]); if(minute < 1 || minute >= 60){ throw new DateTimeException("Invalid day number"); } } catch (DateTimeException e) { System.out.println(e.getMessage()); } } }
int형은 60이상 들어가도 프로그램상 문제가 되지않지만 1시간만 측정할 수 있는 타임스톱을 만든다면 문제가 될 것이다. 그럴 경우 60이상 숫자가 들어올 경우 throw new를 통해 예외를 발생시키고 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
import java.time.DateTimeException; //2시간 까지 측정할 수 있는 타임스톱 public class ThrowTest { public static void main(String[] args) { int minute=0; int hour=0; try { minute = Integer.parseInt(args[0]); if(minute < 1 || minute >= 60){ throw new DateTimeException("Invalid day number"); } } catch (DateTimeException e) { if(minute > 60 && minute < 120){ hour++; minute-=60; } else{ System.out.println(e.getMessage()); return; } } System.out.println(hour+":"+minute); } }
2시간으로 확장을 한다면 위와같이 작성할수 있을 것이다.
finally 절
- try-catch 예외 처리문에서 예외의 발생 여부와 상관없이 무조건 실행됨
- 예외 발생시에도 반드시 실행되어야 하는 구문들을 처리할 때 사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.InputMismatchException;
import java.util.Scanner;
public class FinallyTest {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
try {
int i = scan.nextInt();
} catch (InputMismatchException e) {
System.out.println("please input int type");
} finally{
scan.close();
}
}
}
예외 발생시 오류발생 줄 이후에 있는 모든 줄은 생략이 된다. 그렇기 때문에 finally를 통해 scanner를 닫아준다.
try-with-resource
- 예외발생 여부와 상관없이 사용한 try 절에 명시한 객체의 close() 메소드를 호출
- 스트림, 소켓, 데이터베이스 연결 들을 finally절에서 close() 메소드를 명시적으로 호출하지 않아도 연결을 닫고 리소스를 화수
1
2
3
4
5
6
7
8
9
10
11
12
13
import java.util.InputMismatchException;
import java.util.Scanner;
public class FinallyTest {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
try {
int i = scan.nextInt();
} catch (InputMismatchException e) {
System.out.println("please input int type");
}
}
}
즉, scanne r의 경우 finally를 생략해도 된다.
LAB 4-2: 예외처리
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
import java.util.Scanner;
public class Whatday {
static int[] daysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static int[] daysInLeapMonth = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static String[] monthNames = {"January", "Feburary", "March", "April", "May", "June", "July", "August", "Sepetember", "October", "November", "December"};
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
try {
System.out.print("Enter year number: ");
int yearNum = scanner.nextInt();
boolean isLeapYear = (yearNum % 4 == 0) && (yearNum % 100 == 0 && yearNum % 400 == 0);
int maxDayNum;
if(isLeapYear){
System.out.println("Leap year!");
maxDayNum=366;
}
else{
System.out.println("Common year!");
maxDayNum=365;
}
System.out.print("Enter a day Number between 1 and " + maxDayNum + ": ");
int dayNum = scanner.nextInt();
if (dayNum < 1 || dayNum > maxDayNum) {
throw new IllegalArgumentException("Out of date range");
}
int monthNum = 0;
if (isLeapYear) {
for (int days: daysInLeapMonth) {
if (dayNum > days) {
dayNum -= days;
monthNum++;
}
else break;
}
}
else {
for (int days: daysInMonth) {
if (dayNum > days) {
dayNum -= days;
monthNum++;
}
else break;
}
}
String monthName = monthNames[monthNum];
System.out.printf("%s, %d \n", monthName, dayNum);
}
catch (Exception e) {
e.printStackTrace();
}
finally {
scanner.close();
}
}
}