에러 관계도



이처럼 프로그램 실행 시 발생할 수 있는 예외(Exception)를 대비해 코드를 작성하는 것을 예외처리(Exception handling) 라고 하며 

프로그램의 비정상 종료를 막고 정상적인 실행상태를 유지하는 것이 목적이다!




○ 예외의 종류


자바에서는 에외와 에러를 클래스로 정의 하였다. 역시 Object가 최상위 클래스 이다.

예외클래스 계층도



예외는 그 특징에 따라 크게 2가지로 다시 나뉘어진다.

예외의 두종류


RuntimeException클래스와 아이들 (위 그림에 아랫부분)  //이하 RuntimeException클래스들


RuntimeException클래스와 아이들 제외한 나머지 Exception클래스와 아이들 (위 그림에 윗부분) //이하 Exception클래스들



 RuntimeException클래스들 


-주로 프로그래머의 실수에 의해 발생되는 예외다. (배열의 범위를 벗어남, 정수를0으로나누려함 등등등)

-so 프로그래머의 주의필요

-이런종류의 예외들은 예외처리 없어도 컴파일이 된다. 

-unchecked예외라고 부른다



 Exception클래스들


-주로 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외 (입력한 데이터 형식이 잘못됨, 존재하지 않는 파일 이름 입력 등등등)

-이런종류의 예외들은 반드시 예외처리가 필요함 

-checked예외라고 부른다





○ 예외 처리 방법

try catch, method에 선언하기 2가지가있다.


1. try catch 문



-보기와 같이 catch문은 여러번 쓸 수 있다.


try문에서 예외가 발생하면 해당하는 클래스의 인스턴스가 만들어지고 그 인스턴스를 가지고 catch문에 선언된 참조변수의 종류와 instanceof 연산자를 이용해 true인 catch문을 찾는다.


그래서 먼저 나오는 catch문에 예외는 뒤에 나오는 예외보다 자식이어야 한다!

why? 만약 첫 catch문에 가장 부모인 Exception이 있다면 모든 예외가 다잡하기에 밑에 선언된 catch문은 쓸모가 없어지게 된다. 


-catch문 괄호안의 선언된 변수는 그 catch문 안에만 유효하므로 보기의 'e'처럼 반복사용 가능하다.


-try문이나 catch문 안에 또 try catch문 선언이 가능하다.


-if문과 달리,  try와 catch문의 포함된 문장이 하나여도 {}를 생략할 수 없다


-흐름

예외가 있을경우 : try문(예외까지만) -> 해당되는 예외의 catch문 -> finally문

예외가 없을경우 : try문 -> finally문

try문에서 예외가 발생하면 나머지 try문은 실행되지 않으므로 try문을 잘 구성해야 한다.



-printStackTrace() : 예외발생 당시의 스택에 있던 메서드의 정보와 예외 메시지를 출력한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

class Excep {
    public static void main(String args[]){
        System.out.println(1);
        try{
            System.out.println(2);
            System.out.println(0/0);
            System.out.println(3);  //위에서 예외가 발생해서 실행되지 않는다
        }catch(ArithmeticException e){
            System.out.println(4);
e.printStackTrace(); //
        }finally {
            System.out.println(5);
        }
        System.out.println(6);
    }
}

cs

1

2

4

java.lang.ArithmeticException: / by zero

at blog.Excep.main(Excep.java:8)

5

6


다음과 같이 6번줄에 예외가 발생하여 7번줄이 실행되지 않았고 catch문으로 흐름이 이동해 4와 예외 메시지가 출력되었다.


-멀티 catch 블럭

JDK1.7부터 여러 catch문을 | 을 이용해서 하나로 합칠 수 있게 되었다. 합치는 개 수에는 제한이 없다.


1
2
3
4
5
6
7
8
try{
}catch(ExceptionA e){
 
}catch(ExceptionB e){
 
}catch(Exceptionc e){
 
}
cs

1
2
3
4
try{
}catch(ExceptionA | ExceptionB | ExceptionC e){
 
}
cs

예외 종류는 다르지만 처리방법이 같았던 경우 중복 코드가 생겼었지만 위 방법으로 중복을 피할 수 있다.


한 catch문에 부모 자식 관계에 예외를 사용하지 못한다. 의미가 없다 그냥 조상 클래스의 예외만 써주는 거랑 똑같다.


참조변수 e가 어떤 예외클래스를 참조하는지 알 수 없기 때문에 참조변수 e로는 공통 조상 클래스에 멤버만 쓰거나 instanceof 로 확인 후 써야한다.


1
2
3
4
5
6
7
8
9
try{
}catch(ExceptionA | ExceptionB | ExceptionC e){
    if(e instanceof ExceptionA){
        ExceptionA e1 = (ExceptionA)e;
        e1.methodA();
    }else if(e instanceof ExceptionB){
        ......
    }
cs





* 고의로 예외 발생시키기 (throw)

Exception e = new Exception(); 

throw e;


throw new Exception();  아까 말했듯이 반드시 예외처리 필요

throw new RuntimeException();  예외처리 없어도 됨

이렇게 예외처리가 없어서 에러가 뜬다.


예외처리 해주므로 빨간줄 사라짐~


반면 RuntimeException 에러는 예외처리 안해주어도 컴파일 가능! (하지만 실행시 에러가 발생하면 마찬가지로 프로그램 종료됨)




2. 메소드에 예외 선언하기 (예외 던지기)


method () throws Exception1, Exception2 {


}


throws 키워드를 사용하며 역시 , 로 여러 예외를 선언할 수있다. (throw 랑 헷갈리지 말자)



 사실 메소드에 예외를 선언하는건 예외를 처리하는건 아니다. 

저렇게 선언된 메소드에서 에러가 발생하면 그메소드를 호출한 메소드에게 예외를 전달하여 예외처리를 떠맡기는 것이다.


 그렇게 던지고 던져서 만약 main메소드까지 전달되고 main에서도 예외가 처리되지 않으면 프로그램은 종료된다.

이렇게말이다. 저 에러코드로 알수있는 점이 있는데 예외가 발생한 곳은 method1이고 그메소드를 main이 호출했다는 것을 알 수 있다.

 



결국 어디서든 try catch문으로 예외처리가 필요하다

3가지 처리 방법이 있는데




예외가 발생하는곳에서 처리하는경우

 method1 에서 처리

 

 예외가 발생하는 메소드에서 처리를 해버리는 경우다. 이런 경우에는 main은 예외가 발생하는 지도 모르며 그래서 main에 throws가 필요없다.




예외를 받아 처리하는경우

main에서 처리

 

 예외가 발생하는 method1에서는 예외처리를 하지 않으므로 throws를 해주어야한다. (Exception 예외 이므로)




두곳다 처리하는경우



method1에서 처리

main에서 처리


에러가 발생한 method1에서 처리를 해주고 아까배운 throw로 다시 예외를 만들었다. (예외 되던지기)

이미 처리가 끝난다음에 에러가 발생해 method1에서 다시 throws를 해주어야하고 (역시Exception 에러므로) 

이 에러는 main으로 던져진다 

main에서 역시 try catch로 예외처리 해주어야 된다.




참조

http://sjh836.tistory.com/122

http://history1994.tistory.com/10?category=668240

Java의 정석    남궁 성 지음



+ Recent posts