1.프로그램 오류와 예외 처리
▶ 컴파일 에러(compile-time error)와 런타임 에러(runtime error)
- 컴파일 에러 - 컴파일할 때 발생하는 에러 -
런타임 에러 - 실행할 때 발생하는 에러
▶ Java의 런타임 에러
- 에러(error)와 예외(exception) -
에러(error)는 어쩔 수 없지만, 예외(exception)는 처리해야 한다.
2.try~catch문
- try 영역에서 발생한 예외상황은 이어서 등장하는 catch 영역에서 처리한다.
- 처리할 문장이 단문이라도 중괄호{} 를 생략해서는 안된다.
try { /* 예외 발생 가능 지역 */ }
catch(처리 되어야 할 예외의 종류)
{ /* 예외를 처리하는 코드 */ }
3.e.getMessage() 메소드
- ArithmaticException 클래스와 같이 예외상황을 알리기 위해 정의된 클래스를 가리켜 예외 클래스라 한다.
- 모든 예외클래스는 Throwable클래스를 상속하며, 이 클래스에는 getMessage메소드가 정의되어 있다.
- getMessage 메소드는 예외가 발생한 원인정보를 문자열의 형태로 반환한다.
4.대표적인 예외 클래스
ArrayIndexOutOfBoundsException: 배열의 접근에 잘못된 인덱스 값을 사용하는 예외상황
ClassCastException: 허용할 수 없는 형변환 연산을 진행하는 예외상황
NegativeArraySizeException: 배열선언 과정에서 배열 크기를 음수로 지정하는 예외상황
NullPointerException: 참조변수가 null로 초기화 된 상황에서 메소드를 호출하는 예외상황
5.항상 실행되는 finally
- 그냥 무조건, 항상 실행되는 것이 아니라, finally와 연결되어 있는 try 블록으로 일단 진입을 하
면, 무조건 실행되는 영역이 바로 finally 블록이다.
- 중간에 return 문을 실행하더라도 finally 블록이 실행된 다음에 메소드를 빠져나간다.
예제 1.
class FinallyTest
{
public static void main(String[] args)
{
boolean divOK=divider(4, 2);
if(divOK)
System.out.println("연산 성공");
else
System.out.println("연산 실패");
divOK=divider(4, 0);
if(divOK)
System.out.println("연산 성공");
else
System.out.println("연산 실패");
}
public static boolean divider(int num1, int num2)
{
try
{
int result=num1/num2;
System.out.println("나눗셈 결과는 "+result);
return true;
}
catch(ArithmeticException e)
{
System.out.println(e.getMessage());
return false;
}
finally
{
System.out.println("finally 영역 실행");
}
}
}
실행결과
1. boolean divOK=divider(4, 2);가 실행되서 4/2 결과 2가 나옴
2. finally 실행
3. 연산이 성공하여 true를 반환하여 연산 성공 출력
4.divOK=divider(4, 0);가 실행되어 오류 메세지 출력
5. finally 실행
6. 연산이 실해하여 false를 반환하여 연산 실패 출력
6.프로그래머가 직접 정의하는 예외 클래스의 정의와 throw
- 나이를 입력하라고 했더니, 음수를 입력하는 경우
- 주민등록번호 13자리만 입력해야 되는데, 14자리를 입력하는 경우
- 이와 같은 상황은 프로그램의 논리적 예외상황이다. 즉, 프로그램의 성격에 따라 결정이 되는 예외
상황이다. 따라서 이러한 경우에는 예외 클래스를 직접 정의해야 하고, 예외의 발생도 직접 명시해
야 한다.
- 예외 클래스는 Throwable의 하위 클래스인 Exception 클래스를 상속해서 정의한다.
- Exception 클래스의 생성자로 전달되는 문자열이 getMessage 메소드 호출시 반환되는 문자열이다.
- 예외 상황이 메소드내에서 처리되지 않으면, 메소드를 호출한 영역으로 예외의 처리가 넘어간다.
예제 2.
class AgeInputException extends Exception //예외 클래스 정의 방법
{
public AgeInputException()
{
super("유효하지 않은 나이가 입력되었습니다.");
//super("----")안에 입력하면 getMessage() 메소드를 통해서 출력이 가능하다.
}
}
-------------------------------------------------------------------------------------------------
public class MenuSelectExection extends Exception{ //예외처리를 위해서 만든 클래스
public MenuSelectExection(int menuNum) {
System.out.println(menuNum+"은 잘못된 입력입니다.");
System.out.println("다시 입력하세요");
}
}
---------------------------------------------------------------------------------------------------
public class PhoneBook {
public static Scanner sc=new Scanner(System.in); //System 클래스의 static 참조변수 in:은 인스턴스를 가르킨다.
public static void main(String[] args) {
int menuNum;
PhoneBookManager manager=new PhoneBookManager();
while(true) {
try {
showMenu();
menuNum=sc.nextInt();
if(menuNum<Choice.INPUT || menuNum>Choice.EXIT) {
throw new MenuSelectExection(menuNum); }
//.scnextlnt()안에 문자를 입력하거나 1~5까지 숫자가 아닌 숫자가 들어가게되면 오류가 발생하고
문자 입력은 catch(InputMismatchException e) 쪽으로 던지고 숫자 입력 오류는 catch (MenuSelectExection e) 쪽으로 던저서 예외처리를 한다.
// MenuSelectExection는 예외처리를 목적으로 만든 클래스이다.
switch(menuNum) {
case Choice.INPUT: //1
manager.inputData();
break;
case Choice.SEARCH: //2
manager.searchData();
break;
case Choice.DEL: //3
manager.deleteData();
break;
case Choice.SHOWALL: //4
manager.showAll();
break;
case Choice.EXIT: //5
System.out.println("프로그램 종료");
return;
}
}//try End
catch (MenuSelectExection e) {
e.getMessage();
System.out.println("메뉴로 돌아갑니다.");
}//catch End
catch(InputMismatchException e) {
e.printStackTrace();
System.out.println("메뉴로 돌아갑니다.");
System.out.println("메뉴는 정수로 입력하세요.");
sc.nextLine(); //입력 버퍼의 데이터를 삭제
}
}//while End
}//Main End
----------------------------------------------------------------------------------
public void inputData() throws MenuSelectExection, InputMismatchException
//MenuSelectExection 오류나 InputMismatchException 오류가 발생하면 실행을 중지하고 메소드 밖으로 오류를 던진다. 그럼 main에 있는 try~catch 쪽으로가 예외처리가 실행된다.
{
System.out.println("데이터 입력을 시작합니다.");
System.out.println("1.일반 2.대학 3.회사");
System.out.print("선택:");
int subMenu=PhoneBook.sc.nextInt();
if(subMenu<1 || subMenu>3) {
throw new MenuSelectExection(subMenu);
}
switch(subMenu) {
case 1: //일반
phoneList[cnt] = info.inputInfo();
cnt++;
break;
case 2: //대학
phoneList[cnt] = info.inputInfo();
cnt++;
break;
case 3: //회사
phoneList[cnt] = info.inputInfo();
cnt++;
break;
}
}
예외 클래스의 분류는 크게 두 그룹으로 나뉜다.
Exceptioin 클래스들 - 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외 (예외처리 필수)
RuntimeException 클래스들 - 프로그래머의 실수로 발생하는 예외 (예외처리 선택)