주니 개발 도서관

자바(JAVA)

(14) Exception(try,catch,throw)

주니홍 2022. 6. 24. 12:06
0624 정리

[ 예외와 예외처리]

 

Exception 예외

문법상으로는 문제가 없었는데

실제로 수행해보니 발생하는 문제

실행중에 예외가 발생한다면 프로그램이 즉시종료

 

지연이 되는것과 종료가 되는것

사용자에게 있어선 오류가 난다고 해서 "종료" 하는것 보다

당연히 "지연"되는것이 "종료"보다 낫다

 

그래서 

 

예외처리 목적

" 프로그램이 즉시 종료되는 현상을 방어 "

이것을 최우선 목적으로 둔다고 생각해야한다

 

 

예외 발생시 해야할 일

1.  어떤타입의 예외인지 파악

(클래스화 되어있다)

 

2.  원인 파악

콘솔내의 설명 참고해 볼것

 

3.  발생한 라인

 

4. 스크린샷 

 

5. 블로그 포스팅 ★

 

 


예외처리 하는방법

 

try & catch 문을 이용한다

 

사용법

 

try {

 

예외발생할만한 구간

 

} catch ( 예상되는 에러 e) {

에러뒤에 e 라는 객체명은 보편적으로 쓰는거 같다

예상되는 에러를 만났을때 실행되는 구간

 

} finally {

 

예외발생여부와 상관없이 수행되는 구간

 

}

 

try의 바디

예외가 발생할만한 구간을 설정

예외가 발생한 즉시 catch로 즉시 이동한다

 

catch()의 바디

예상되는 예외처리를 catch() 잡았다 하더라도

못찾은 예외처리가 있을수 있기때문에

마지막에는 최상위 Exception 클래스인

catch ( Exception e )마지막넣어

catch (Exception e) 바디에는

e.printStackTreace()

내가 아직 막지못한 에러를 확인하면 좋을 것 같다

 

무슨 에러였는지 (개발자)

어떻게 해야하는지 (사용자)

해당에러 이유를 해당바디에 설명(출력)해 준다

 

 

finally 의 바디

예외발생 여부와 상관없이 수행되는 구간이며

try & catch는 항상 붙어다니지만

finally는 안만들어도 상관없다!

 

그럼 왜 사용하느냐?

try와 catch 문에서 return 을 만나게 되면 프로그램은 무조건 중단이 됩니다.

try 구문 바깥에 예외 발생 여부에 관계 없이 원하는 코드를 작성한다고 한들

리턴값을 돌려주게 되면 메서드를 빠져나와 실행이 될 수가 없습니다

그래서 try catch 구문 내에 동일한 코드를 반복적으로 작성을 해주어야만 하는데

이 때 중복되는 코드를 줄여줄 수 있는 장점이 있습니다.

 

 

Excepsion클래스마다import 해주어야 사용가능한 클래스가 존재한다

 

 


 

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
    public static void main(String[] args) {
 
        ArrayList<Integer> al = new ArrayList<Integer>();
 
        for(int i = -1; i < 4; i++) { // -1 ~ 3 까지 저장
            al.add(i);
        }
        System.out.println("로그 : "+al); // 로그 : 배열리스트 확인
 
        Scanner sc = new Scanner(System.in);
        while(true) {
 
            int res = 0;
            try {
                System.out.print("인덱스 넘버입력 : ");
                int num = sc.nextInt();
 
                res = 10/al.get(num);
            }
            catch (InputMismatchException e) {
                System.out.println("정수만 입력 가능하십니다!");
                sc.nextLine();
                continue;
            }
            System.out.println("결과값 : "+res);
            System.out.println("도착!");
            break;
        }
cs

무한으로 돌고 도는 버퍼문제가 있는 코드였다

 

이미 고쳐진 코드이지만 해당 무한루프가 생긴 이유를 보면

 

코드의 try 문안에

int num = sc.nextInt() 에서 정수값을 받도록한다

하지만 우린 "안녕"이라는 문자값을 넣게되면

nextInt()는 문자열값을 받지못하여 try안에서

InputMismatchException 을 발생시킨다

 

입력값이 맞지않았을때 발생한는 오류인데

오류를 catch문에서 오류내용 출력 이후 continue; 를 만나

sc.nextInt()의 입력값을 다시 받지 않고(자동으로 입력됨)

무한루프가 되었기때문에 해당오류는 "버퍼"와 관련있다는걸 알 수 있다.

 

next(), nextInt(),nextDouble()은 버퍼에 엔터값을

담지 못하기 때문에 남아있어도 자동으로 빼주는데

nextLine()은 엔터값을 가지고 갈수 있기때문에

오류가 생긴다  ( 여긴 복습 )

 

그래서 nextInt()에서 문자값을 입력해주면

버퍼입력한문자값 + 엔터값이 저장된다

하지만  try 안에서 예외를 발생하였기 때문에

catch로 바로 이동한다

 

하지만 이때, 버퍼에는 입력한문자값과+엔터값이

존재한 상태에서 catch문안의 continue;를 만나

다시 입력하기위에 sc.nextInt()를 만나면

엔터값은 못 받음을 알기에 자동으로 빼주지만

버퍼에는 입력한문자값은 그대로 남게된다 

버퍼에서 빼주는건 엔터값만 빼준 것

입력한문자값 다시 nextInt()를 만나서 예외를 발생시키고

다시 catch의 continue; 그대로 nextInt() 반복을 하기에

해당 오류가 발생하게 된것이다

 

해결방법은 해당 잘못된 문자값을 버퍼에서 가져가줄 (지워줄)

sc.nextLine() 을 catch 에서 사용해주어 해당 값을 가져가주면

버퍼에는 엔터값만 남게되고 자연스럽게

nextInt()를 만나서 엔터값을 지워주고 입력 받을 수 있을 것이다

 

 


Throw

내가 오류메세지를 던져주자!

 

만약 사용자에게 나이를 입력받아야하는 상황이다

sc.nextInt() 를 사용하여 나이입력을 받을텐데

나이입력 : 102030131 을 입력해도 오류는 나오지않는다

이런상황에서 조건을 걸어 강제로 오류를 던져줄 수 있는데

 

해당 키워드가 throw 이다!

 

 

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
package class02;
 
import java.util.Scanner;
 
// +) 심화과정
// 나만의 예외만들기
class MyException extends Exception {
    private String message;
 
    MyException(String message) {
        this.message = message;
    }
 
    public String getMessage() {
        return message;
    }
 
}
 
public class Test05 {
    public static void main(String[] args) {
 
        MyException me = new MyException("범위에 맞는 나이를 입력해주세요");
        MyException even = new MyException("짝수는 사용하실수 없습니다!");
        
        Scanner sc = new Scanner(System.in);
 
        try {
            System.out.println("나이입력 ) ");
            int age = sc.nextInt();
            if (age < 1 || 200 < age) {// 예외를 일부러 발생시켜야하는 상황
                throw me;
            } else {
                if (age % 2 == 0) { // 짝수를 이용시 오류를 던짐
                    throw even;
                }
            }
        } //--- try 끝 ---
        catch (MyException e) { // throw 해주는 객체의 getMessage()를 던져준다
            System.out.println(e.getMessage());
        }
 
    }
 
}
cs

 

해당코드에서 나이를 입력받아 저장한 변수 age가 있다

inputMismatchException은 제외했다

 

말이 안되는 나이를 입력한다면

"범위에 알맞는 나이를 입력해주세요" 를 출력하고 싶다

 

물론, while문으로 만들어 조건문에 만들 수 있지만

try & catch를 사용하는 이유

오류를 던져서 해결한다면 예외를 발생했다는

이력을 남길수 있기때문이다! ( if문은 안됨 )

 

그렇다면 "범위에 알맞는 나이를 입력해주세요" 만들어야하는데

 

만드는법

 

MyException의 클래스를 만들고 Exception을 상속받은 후

Private String message;를 만들고

생성자에 input값으로 해당 메세지를 적어서 만들게 "강제"

input값을 this.message에 대입시켜놓고

 

게터Message() 메소드를 만들어서 사용하면 된다

멤버변수를 private으로 만들었기 때문이다

 

이제 메인메소드에서

MyException 객체명 = new Myexception( String값 );

input String값이 내가 던져줄 오류 메세지가 되겠다

객체명은 오류과 관계있는 객체명이여야 가독성이 좋다

 

오류가 나올수있는 sc.nextInt()를 try안에 넣고

나이입력을 이상하게 할만한 범위를 조건문으로 가둔다

이상하게 입력했다면 위의 코드값을 참조하여

throw me; 를 던져준다

ㅡ> 처음만든 나의 인셉션클래스여서 객체명이 me

ㅡ> "범위에 맞는 나이를 입력해주세요" 가 메세지값

 

catch문에서 클래스명인 MyException e 객체로 받아오고

해당 객체에는

 

메세지 : "범위에 맞는 나이를 입력해주세요"

getMessage() 존재함

 

catch ( MyException e )의 바디에는

syso( e.getMessage() ) 를 사용한다면

throw 한 객체 me의 메세지를 출력해줄것이다

 

 

다른 하나를 개인적으로 만들어 보았는데

같은 클래스인 MyException 이고

객체명 even

input값으로 "짝수는 사용하실수 없습니다!"

 

age값을 조건문으로 받아와age % 2 == 0 이라면throw even 을 해주었다

 

그리고 catch문에

또다른 MyException e 을 만들어야하는줄 알았다

 

하지만 생각해보니throw에서

MyException의 각각의 객체를 보내고있었다

그렇기때문에 각각의 객체의 메세지를 출력해주기 때문에

따로 catch문을 만들어줄필요가없다는 것을 알게 되었다!!

 

 

 

 

 

 

'자바(JAVA)' 카테고리의 다른 글

(16) 파일 입출력  (0) 2022.06.27
(15) 콜론 ( : ) 의 기능  (0) 2022.06.27
(13) 컬렉션 프레임워크 (ArrayList)  (0) 2022.06.23
(12) 인터페이스  (0) 2022.06.22
(11) 클래스의 다형성, 추상클래스  (0) 2022.06.22