'자바의 정석 3rd Edition'을 공부한 후 정리한 내용입니다.
컴파일 에러 컴파일 시에 발생하는 에러
런타임 에러 실행 시에 발생하는 에러
논리적 에러 실행은 되지만, 의도와 다르게 동장하는 것
에러(error) 프로그램 코드에 의해서 수습될 수 없는 심각한 오류
- ex) 메모리 부족, 스택오버플로우
예외(exception) 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류
자바에서는 실행 시 발생할 수 있는 오류(exception, error)를 클래스로 정의
모든 예외의 최고 조상은 Exception 클래스
사진 출처: https://velog.io/@orpsh1941/JAVA%EC%9D%98-%EC%A0%95%EC%84%9D%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC
예외 클래스는 두 급룹으로 나눠짐
예외처리(exception handling)
발생한 예외를 처리하지 못하면 프로그램은 비정상적으로 종료되며, 처리되지 못한 예외는 JVM의 '예외 처리기'가 받아서 예외의 원인을 화면에 출력
예외 처리를 위해서는 try-catch문을 사용
try {
// 예외가 발생할 가능성이 있는 문장을 넣음
} catch (Exception1 e1) {
// Exception1이 발생했을 경우, 이를 처리하기 위한 문장을 적음
} catch (Exception2 e2) {
// Exception2이 발생했을 경우, 이를 처리하기 위한 문장을 적음
} catch (Exception3 e3) {
// Exception3이 발생했을 경우, 이를 처리하기 위한 문장을 적음
}
try 블럭 내에서 예외가 발생한 경우
1. 발생한 예외와 일치하는 catch 블럭이 있는지 확인
2. 일치하는 catch 블럭을 찾게 되면, catch 블럭 내의 문장들을 수행하고 전체 try-catch문을 빠져나가 그 다음 문장을 계속해서 수행. 만일 일치하는 catch 블럭을 찾지 못하면, 예외는 처리되지 못함
- try 블럭에서 예외가 발생하면, 예외가 발생한 위치 이후에 있는 try 블럭의 문장들은 수행되지 않음
try 블럭 내에서 예외가 발생하지 않는 경우
1. catch 블럭을 거치지 않고 전체 try-catch문을 빠져나가 수행을 계속
printStackTrace()와 getMessage()
printStackTrace() 예외발생 당시의 호출스택에 있었던 메서드의 정보와 예외 메시지를 화면에 출력
getMessage() 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있음
멀티 catch블럭
- 연산자 new를 이용해서 발생시키려는 예외의 클래스 객체를 만듦
Exception e = new Exception("고의로 발생시켰음");
- 키워드 throw를 이요해서 예외를 발생시킴
throw e;
getMessage()
를 이용해서 얻을 수 있음void method() throws Exception1, Exception2, ..., ExceptionH {
// 메서드의 내용
}
throws
를 사용해 메서드 내에서 발생할 수 있는 예외를 적어줌throw
(예외를 발새시키는 키워드)와 구분throws
에는 반드시 처리해주어야 하는 예외들만 선언try-catch
문으로 예외를 처리해줘야 함try-catch
문을 사용. 메서드에 호출 시 넘겨받아야 할 겂을 다시 받아야 하는 경우(메서드 내에서 자체적으로 해결이 안 되는 경우)에는 예외를 메서드에 선언해서, 호출한 메서드에서 처리해야 함try {
// 예외가 발생할 가능성이 있는 문장
} catch (Exception1 e1) {
// 예외처리를 위한 문장
} finally {
// 예외의 발생여부에 관계없이 항상 수행되어야 할 문장
// finally 블럭은 try-catch문의 맨 마지막에 위치해야함
}
try-with-resource
문의 괄호()안에 객체를 생성하는 문장을 넣으면, 이 객체는 따로 close()
를 호출하지 않아도 try 블럭을 벗어나는 순간 자동적으로 close()
가 호출됨. 그 다음 catch 블럭 또는 finally 블럭이 실행됨try-with-resource
문에 의해 자동으로 객체의 close()
가 호출될 수 있으려면, 클래스가 AutoCloseable
이라는 인터페이스를 구현한 것이어야 함예시
class TryWithResourceEx {
public static void main(String args[]) {
try (CloseableResource cr = new CloseableResource()) {
cr.exceptionWork(false); // 예외가 발생하지 않는다.
} catch(WorkException e) {
e.printStackTrace();
} catch(CloseException e) {
e.printStackTrace();
}
System.out.println();
try (CloseableResource cr = new CloseableResource()) {
cr.exceptionWork(true); // 예외가 발생한다.
} catch(WorkException e) {
e.printStackTrace();
} catch(CloseException e) {
e.printStackTrace();
}
} // main의 끝
}
class CloseableResource implements AutoCloseable {
public void exceptionWork(boolean exception) throws WorkException {
System.out.println("exceptionWork("+exception+")가 호출됨");
if(exception)
throw new WorkException("WorkException발생!!!");
}
public void close() throws CloseException {
System.out.println("close()가 호출됨");
throw new CloseException("CloseException발생!!!");
}
}
class WorkException extends Exception {
WorkException(String msg) { super(msg); }
}
class CloseException extends Exception {
CloseException(String msg) { super(msg); }
}
/*결과*/
exceptionWork(false)가 호출됨
close()가 호출됨
CloseException: CloseException발생!!!
at CloseableResource.close(TryWithResourceEx.java:33)
at TryWithResourceEx.main(TryWithResourceEx.java:6)
exceptionWork(true)가 호출됨
close()가 호출됨
WorkException: WorkException발생!!!
at CloseableResource.exceptionWork(TryWithResourceEx.java:28)
at TryWithResourceEx.main(TryWithResourceEx.java:14)
Suppressed: CloseException: CloseException발생!!!
at CloseableResource.close(TryWithResourceEx.java:33)
at TryWithResourceEx.main(TryWithResourceEx.java:15)
main
메서드try-catch
문 중 첫 번째는 close()에서만 예외를 발생시키고, 두 번째는 exceptionWork()와 close()에서 모두 예외를 발생시킴try-catch
문에서는 finally
블럭에 try-catch
문을 추가해 예외를 처리해줄 수 있지만, 만약 try
블럭과 finally
블럭에서 모두 예외가 발생하면 try
블럭의 예외는 무시됨
- 예외가 발생할 가능성이 있는 메서드에서 try-catch문을 사용해서 예외를 처리해줌
- catch문에서 필요한 작업을 행한 후 throw문을 사용해서 예외를 다시 발생시킴
- 다시 발생한 예외는 메서드를 호출한 메서드에게 전달되고 호출한 메서드의 try-catch문에서 예외를 또 다시 처리
throws
에 지정해줘야 함Throwable initCause(Throwable cause) 지정한 예외를 원인 예외로 등록
Throwable getCause() 원인 예외를 반환
발생한 예외를 원인 예외로 등록한 후 다시 예외를 발생시키는 이유
- 여러가지 예외를 하나의 큰 분류의 예외로 묶어서 다루기 위함
- checked 예외를 unchecked 예외로 바꿀 수 있게 하기 위함
- checked 예외로 예외처리를 강제한 이유는 프로그래밍 경험이 적은 사람도 견고한 프로그램을 작성할 수 있도록 유도하기 위한 것
- 현재는 컴퓨터 환경이 많이 달라져, checked 예외가 발생해도 예외를 처리할 수 없는 상황이 발생하기 시작
- 이럴 때 의미없는 try-catch문을 추가할 필요없이 checked 예외를 unchecked 예외로 바꾸면 예외처리가 선택적이 되므로 억지로 예외 처리를 하지 않아도 됨
Chapter 8 끝!!!