본문 바로가기
아카이브/자바의 정석

8장 예외처리 20201012

by nineteen 2020. 10. 12.
반응형

finally블록

 

try-catch문 끝에 선택적으로 덧붙여 사용

예외의 발생여부에 관계없이 실행되어야 할 코드를 작성

 

1
2
3
4
5
6
7
try {
    // 예외가 발생할 가능성 있는 문장
catch (Exception e) {
    // 예외처리를 위한 문장
finally {
    // 예외의 발생여부에 관계없이 항상 수행되어야 할 문장
}
cs

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class FinallyTest3 {
    
    static void method1() {
        try {
            System.out.println("method1()메소드가 실행중");
            return// 메소드 종료
        } catch(Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("method1()의 finally블럭 실행!"); // 무조건 
        }
    }
    
    public static void main(String[] args) {
        FinallyTest3.method1();
        System.out.println("method1()의 수행을 마치고 main메소드");
    }
}
 
cs

 

출력

method1()메소드가 실행중
method1()의 finally블럭 실행!
method1()의 수행을 마치고 main메소드

 

 

 

 

 

 

try-with-resources문

 

입출력과 관련된 클래스를 사용할 때 유용,

입출력에 사용되는 클래스 중에서 사용한 후에 꼭 닫아 줘야 하는 것들이 있음

그래야 사용했던 자원(resources)이 반환되기 때문

 

괄호()안에 객체를 생성하는 문장을 넣으면, 이 객체는 따로 close()를 호출하지 않아도,

try블럭을 벗어나면 자동적으로 close()가 호출됨

 

try-with-resources문에 의해 자동으로 객체의 close()가 호출될 수 있으려면,

클래스가 AutoCloseable이라는 인터페이스를 구현한 것이어야 함

1
2
3
4
public interface AutoCloseable {
    void close() throws Exception;
}
 
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
package exception;
 
// 사용자정의 예외
class WorkException extends Exception {
    WorkException(String msg) {    super(msg);    }
}
 
// 사용자정의 예외
class CloseException extends Exception {
    CloseException(String msg) { super(msg); }
}
 
// try-with-resources문 작성을 위한 AutoCloseable인터페이스를 구현한 임의의 클래스 작성
class CloseableResource implements AutoCloseable {
    // 예외를 발생시키는 메소드, true면 예외 발생시킴
    public void exceptionWork(boolean exception) throws WorkException {
        System.out.println("exceptionWork("+exception+")가 호출됨!");
        
        if(exception)
            throw new WorkException("WorkException발생!");
    }
 
    @Override
    public void close() throws CloseException {
        // close()를 호출하면 예외발생시킴
        System.out.println("close()가 호출됨");
        throw new CloseException("CloseException발생!");
    }
}
 
public class TryWithResourcesEx {
    public static void main(String[] args) {
        // try-with-resources문
        try(CloseableResource cr = new CloseableResource()) {
            cr.exceptionWork(false); 
            // try문 이후에 자동으로 close()메소드 실행
        } catch(WorkException e) {
            e.printStackTrace();
        } catch(CloseException e) {
            e.printStackTrace();
        }
        System.out.println();
        
        try(CloseableResource cr = new CloseableResource()) {
            cr.exceptionWork(true); // WorkException예외 발생
            // try문 이후에 자동으로 close()메소드 실행
        } catch(WorkException e) {
            e.printStackTrace();
        } catch(CloseException e) {
            e.printStackTrace();
        }
 
    }
 
}
 
cs

출력

exceptionWork(false)가 호출됨!
close()가 호출됨

exception.CloseException: CloseException발생!


exceptionWork(true)가 호출됨!
close()가 호출됨

          at exception.CloseableResource.close(TryWithResourcesEx.java: 25)

          at exception.TryWithResourceEx.main(TryWithResourcesEx.java: 34)

exception.WorkException: WorkException발생!

          at exception.CloseableResource.exceptionWork(TryWithResourcesEx.java: 19)

          at exception.TryWithResourceEx.main(TryWithResourcesEx.java: 42)

          Suppressed: exception.CloseException: CloseException발생!

                      at exception.CloseableResource.close(TryWithResourcesEx.java: 25)

                      at exception.TryWithResourceEx.main(TryWithResourcesEx.java: 43)

 

 

 

 

 

 

 

 

사용자정의 예외 만들기

 

기존에 정의된 예외 클래스 외에 필요에 따라 새로운 예외 클래스를 정의하고 사용할 수 있음

1
2
3
4
5
class MyException extends Exception {    // 사용자 예외 클래스 정의위해 Exception클래스 상속
    MyException(String msg) {            // Exception클래스의 생성자 호출, 
        super(msg);
    }
}
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
package exception;
 
// 사용자정의 예외
class SpaceException extends Exception {
    SpaceException(String msg) { super(msg); }
}
 
// 사용자정의 예외
class MemoryException extends Exception {
    MemoryException(String msg) { super(msg); }
}
 
public class NewExceptionTest {
    
    // 메소드에 예외선언, 이 메소드를 호출한 메소드에서 예외 처리
    static void startInstall() throws SpaceException, MemoryException {
        if(!enoughSpace())
            throw new SpaceException("설치할 공간이 부족해요"); // 예외 발생
        if(!enoughMemory())
            throw new MemoryException("메모리가 부족해요"); // 예외 발생
    }
    
    static void copyFiles() { /* 파일들을 복사하는 코드 */ }
    static void deleteTempFiles() { /* 임시파일들을 삭제하는 코드 */ }
    
    static boolean enoughSpace() {
        // 설치하는데 필요한 공간이 있는지 확인하는 코드
        return false;
    }
    
    static boolean enoughMemory() {
        // 설치하는데 필요한 메모리공간이 있는지 확인하는 코드
        return true;
    }
    
    public static void main(String[] args) {
        try {
            startInstall();        // 프로그램 설치에 필요한 준비를 한다
            copyFiles();        // 파일들을 복사
        } catch(SpaceException e) {
            System.out.println("에러메세지 : " + e.getMessage());
            e.printStackTrace();
            System.out.println("공간을 확보한 후에 다시 설치해주세요");
        } catch(MemoryException e) {
            System.out.println("에러메세지 : " + e.getMessage());
            e.printStackTrace();
            System.gc(); // Garbage Collection을 수행해 메모리를 늘려줌
        } finally {
            deleteTempFiles();    // 프로그램 설치에 사용된 임시파일들을 삭제
        }
 
    }
 
}
 
cs

출력

에러메세지 : 설치할 공간이 부족해요

exception.SpaceException: 설치할 공간이 부족해요

공간을 확보한 후에 다시 설치해주세요

                at exception.NewExceptionTest.startInstall(NewExceptionTest.java:18)

                at exception.NewExceptionTest.main(NewExceptionTest.java:38)

 

 

 

 

 

 

 

 

 

예외 되던지기

 

한 메소드에서 발생할 수 있는 예외가 여럿인 경우,

몇 개는 try-catch문을 통해서 메소드 내에서 자체적으로 처리하고,

그 나머지는 선언부에 지정하여 호출한 메소드에서 처리하도록 함으로써

양쪽에서 나눠서 처리되도록 할 수 있다

 

단 하나의 예외에 대해서도 예외가 발생한 메소드와 호출한 메소드, 양쪽에서 처리하도록 할 수 있음

예외를 처리한 후 인위적으로 다시 발생시키는 '예외 되던지기'를 통해서 가능함

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package exception;
 
public class ExceptionEx17 {
    static void method1() throws Exception {
        try {
            throw new Exception(); // 예외 발생
        } catch(Exception e) {
            System.out.println("method1()에서 예외가 처리되었음");
            throw e; // 다시 예외 발생시킴
        }
    }
    
    public static void main(String[] args) {
        try {
            method1();
        } catch(Exception e) {
            System.out.println("main메소드에서 예외 처리되었음");
        }
    }
}
 
cs

출력

method1()에서 예외가 처리되었음
main메소드에서 예외 처리되었음

 

 

 

 

 

 

 

연결된 예외

 

원인 예외 - 예외 A가 예외 B를 발생시켰다면, A를 B의 '원인 예외'라고 함

 

Throwable initCause(Throwable cause)  지정한 예외를 원인 예외로 등록

Throwable getCause()                       원인 예외를 반환

RuntimeException(Throwable cause)     원인 예외를 등록하는 생성자

 

 

연결된 예외를 사용하는 이유는,

여러가지 예외를 하나의 큰 분류의 예외로 묶어서 다루기 위함

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
package exception;
 
// 사용자정의 예외
class InstallException extends Exception {
    InstallException(String msg) { super(msg); }
}
 
// 사용자정의 예외
class SpaceException extends Exception {
    SpaceException(String msg) { super(msg); }
}
 
// 사용자정의 예외
class MemoryException extends Exception {
    MemoryException(String msg) { super(msg); }
}
 
public class ChainedExceptionEx {
 
    public static void main(String[] args) {
        try {
            install();
        } catch(InstallException e) {
            e.printStackTrace();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    // SpaceException, MemoryException예외가 발생하면 InstallException예외가 발생
    // SpaceException, MemoryException예외를 하나의 큰 분류인 InstallException예외로 묶음
    static void install() throws InstallException {
        try {
            startInstall();        // 프로그램 설치에 필요한 준비를 한다
            copyFiles();        // 파일들을 복사
        } catch(SpaceException se) {
            InstallException ie = new InstallException("설치 중 예외발생"); 
            ie.initCause(se);    // InstallException의 원인예외를 SpaceException으로 지정
            throw ie;            // InstallException예외 발생
        } catch(MemoryException me) {
            InstallException ie = new InstallException("설치 중 예외발생");
            ie.initCause(me);     // InstallException의 원인예외를 MemoryException으로 지정
            throw ie;            // InstallException예외 발생
        } finally {
            deleteTempFiles();    // 프로그램 설치에 사용된 임시파일들을 삭제
        }
    }
    
    // 메소드에 예외선언, 이 메소드를 호출한 메소드에서 예외 처리
    static void startInstall() throws SpaceException, MemoryException {
        if(!enoughSpace())
            throw new SpaceException("설치할 공간이 부족해요"); // 예외 발생
        if(!enoughMemory())
            throw new MemoryException("메모리가 부족해요"); // 예외 발생
    }
    
    static void copyFiles() { /* 파일들을 복사하는 코드 */ }
    static void deleteTempFiles() { /* 임시파일들을 삭제하는 코드 */ }
        
    static boolean enoughSpace() {
        // 설치하는데 필요한 공간이 있는지 확인하는 코드
        return false;
        }
    
    static boolean enoughMemory() {
        // 설치하는데 필요한 메모리공간이 있는지 확인하는 코드
        return true;
    }
 
}
 
cs

출력

exception.InstallException: 설치 중 예외발생

           at exception.ChainedExceptionEx.install(ChainedExceptionEx.java:37)

           at exception.ChainedExceptionEx.main(ChainedExceptionEx.java:22)

Caused by: exception.SpaceException: 설치할 공간이 부족해요

           at exception.ChainedExceptionEx.startInstall(ChainedExceptionEx.java:52)

           at exception.ChainedExceptionEx.install(ChainedExceptionEx.java:34)

           ... 1 more

 

 

 

 

 

 

너무 꼼꼼하게 보는걸까

진도가 너무 느린거같다

 

잘하고 있는건지 계속 의심된다

 

하나하나 열심히 해보자

'아카이브 > 자바의 정석' 카테고리의 다른 글

9장 java.lang패키지와 유용한 클래스 20201017  (0) 2020.10.17
9장 java.lang패키지와 유용한 클래스 20201014  (0) 2020.10.14
8장 예외처리 20201009  (0) 2020.10.09
7장 20200926  (0) 2020.09.26
7장 20200925  (0) 2020.09.25