📚 Study/JAVA
[JAVA] 예외처리(try-catch문)
0_ch4n
2022. 5. 2. 19:17
반응형
📌 컴파일
- 소스코드(.java) → 컴파일 → 클래스 파일(.class)
- 구문체크, 번역, 최적화, 생략된 코드 추가
📌 프로그램 오류
- 컴파일 에러(compile-time error) : 구문 등의 오류로 실행 전 컴파일 단계에서 잡는 에러
- 런타임 에러(runtime error) : 컴파일은 정상적으로 됐지만 실행 중 JVM에서 발생하는 에러
- 에러(error) : 프로그램 코드에 의해서 수습될 수 있는 심각한 오류
- 예외(exception) : 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류
- 논리적 에러(logical error) : 작성 의도와 다르게 동작하는 에러
- Exception 클래스들(checked 예외) : 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외
- RuntimeException 클래스들(unchecked 예외) : 프로그래머의 실수로 발생하는 예외
📌 예외 처리(exception handling)
- 정의 : 프로그램 실행 시 발생할 수 있는 예외에 대비한 코드를 작성하는 것
- 목적 : 프로그램의 비정상적인 종료를 막고 정상적인 실행상태를 유지하는 것
- 예외처리기(UncaughtExceptionHandler) : 처리하지 못한 예외를 JVM이 받아서 예외의 원인을 화면에 출력하는 것
📌 try-catch문
- try 블럭 내에서 예외가 발생한 경우
- 발생한 예외와 일치하는 catch 블럭을 instanceof 연산자로 확인한다 (일치하는 catch 블럭이 없으면 예외는 처리되지 못한다)
- 일치하는 catch 블럭 내의 문장과 finally 블럭을 수행 후 전체 try-catch문을 빠져나가 다음 문장을 계속해서 수행한다
- 이 때 예외 발생 부분 이후의 문장은 실행되지 않는다
- try 블럭 내에서 예외가 발생하지 않은 경우
- catch 블럭을 거치지 않고 finally 블럭을 거친 후 전체 try-catch 문을 빠져나가서 수행을 계속한다
try {
//예외가 발생할 가능성이 있는 문장들을 넣는다
} catch (예외클래스 참조변수명) {
//예외클래스에 해당하는 예외가 발생했을 경우, 이를 처리하기 위한 문장을 적는다
} catch (예외클래스 | 예외클래스 참조변수명) {
//멀티 catch 블럭으로 jdk1.7부터 생겼다
//'|' 기호를 이용해서 갯수 제한 없이 중복 코드를 줄일 수 있지만 조상-자손 관계는 불가능하다
//메서드는 instanceof를 통해 형변환이 가능한지 확인 후 사용한다 (공통 메서드는 상관없다)
} catch (Exception e) {
//Exception 클래스는 모든 예외 클래스의 조상으로 모든 예외 클래스를 처리 가능
} finally {
//예외의 발생여부에 관계없이 항상 수행되어야하는 문장들을 넣는다
//finally 블럭은 try-catch문의 맨 마지막에 위치해야 한다
}
//if문과 달리 try 블럭이나 catch 블럭 내에 포함된 문장이 하나뿐이어도 괄호{}를 생략 불가능
//catch문 내에서는 참조변수 e는 중복 불가능
- 예외 직접처리 : 메서드 내에서 try-catch문을 통한 예외 처리
- 예외 떠넘기기 : 호출된 메서드에 throws로 예외 선언하고 호출한 메서드에서 try-catch문을 통한 예외 처리
📌 예외 인스턴스의 메서드
- printStackTrace() : 예외발생 당시의 호출스택(Call Stack)에 있었던 메서드의 정보와 예외 메시지를 화면에 출력
- getMessage() : 발생한 예외클래스의 인스턴스에 저장된 메시지나 생성자로 저장된 메시지를 얻을 수 있다
e.printStackTrace() 실행결과
java.lang.ArithmeticException: / by zero
at ExceptionEx8.main(ExceptionEx8.java:7)
e.getMessage() 실행결과
/ by Zero
📌 예외 발생시키기(throw)
- checked 예외는 예외 처리가 필수고 unchecked 예외는 예외 처리가 필수가 아니다
try {
Exception e = new Exception("고의로 발생시킨 예외");
throw e;
// throw new Exception("한 줄로 줄여 쓸 수 있음");
} catch (Exception e) {
System.out.println("에러 메시지 : " + e.getMessage());
e.printStackTrace();
}
📌 메서드에 예외 선언하기 (throws)
- Java API를 사용하는 경우 설명에 'Throws:'를 확인하여 예외처리를 해주어야 한다
- throws는 예외를 처리해주는 것이 아니라 호출한 메서드에게 예외를 떠넘기는 것이다
void method() throws Exception1, Exception2, ... ExceptionN {
//메서드의 내용
}
📌 try-with-resources문
- try-catch문의 변형으로 클래스 사용 후 닫아서 자원을 반환하기 위해 사용한다 (AutoCloseable 인터페이스 구현한 클래스 전용)
- try 블럭의 괄호() 안에는 객체 생성뿐만 아니라 변수도 선언할 수 있고 이 변수는 try 블럭 내에서만 사용된다
- 예외가 두 개가 발생하면 실제 발생한 예외에 억제된 예외를 저장해 다룬다
try (FileInputStream fis = new FileInputStream("score.dat");
DataInputStream dis = new DataInputStream(fis)) {
//수행할 문장
} catch (EOFException e) {
//EOF 예외 발생 시 수행할 문장
} catch (IOException ie) {
//IO 예외 발생 시 수행할 문장
}
📌 사용자 정의 예외
- 조상을 Exception으로 하면 checked 예외이므로 try-catch문을 필수적으로 써야 한다
- 조상을 RuntimeException으로 하면 unchecked 예외이므로 try-catch문을 선택적으로 써도 된다
class MyException extends Exception 또는 RuntimeException {
MyException(String msg) { //문자열을 매개변수로 받는 생성자를 꼭 써줘야함
super(msg); //조상 클래스의 생성자를 호출한다
}
}
📌 예외 되던지기(exception re-throwing)
- 하나의 예외에 대해서 예외가 발생한 메서드와 이를 호출한 메서드 양쪽 모두에서 처리해줘야 할 때 사용한다
- 호출한 메서드와 호출된 메서드에 try-catch문으로 예외를 처리하고 호출된 메서드에는 throws로 예외를 선언해야 한다
class ExceptionThrowing {
public static void main(String[] args) {
try {
method1(); //1번
} catch (Exception e) {
System.out.println("main메서드에서 예외가 처리되었습니다."); //5번
}
}
static void method1() throws Exception {
try {
throw new Exception(); //2번
} catch (Exception e) {
System.out.println("method1메서드에서 예외가 처리되었습니다."); //3번
throw e; //4번
}
}
}
📌 연결된 예외(chained exception)
- Throwable initCause (Throwable cause) : 지정한 예외를 원인 예외로 등록
- Throwable getCause() : 원인 예외를 반환
- 여러가지 예외를 하나의 큰 분류의 예외로 묶어서 다루기 위해 사용
- checked 예외를 unchecked 예외로 바꾸어 의미없는 try-catch문을 사용하지 않기 위해 사용
class ChainedException {
public static void main(String[] args) {
try {
install(); //1번
} catch (InstallException e) {
e.printStackTrace(); //10번 예외 메시지 출력
}
}
static void install() throws InstallException {
try {
startInstall(); //2번
} catch (SpaceException se) {
InstallException ie = new InstallException("설치 중 예외 발생"); //6번 InstallException 생성
ie.initCause(se); //7번 InstallException의 원인 예외로 SpaceException 저장
throw ie; //8번 InstallException 발생
}
}
static void startInstall() throws SpaceException {
if (!enoughSpace()) { //3번 true
throw new SpaceException("설치할 공간이 부족합니다."); //4번
}
if (!enoughMemory()) {
throw new RuntimeException(new MemoryException("메모리가 부족합니다.")); //checked 예외를 unchecked 예외로 변경
}
}
static boolean enoughSpace() {
return false;
}
static boolean enoughMemory() {
return false;
}
}
class InstallException extends Exception {
InstallException(String msg) {
super(msg); //9번
}
}
class SpaceException extends Exception {
SpaceException(String msg) {
super(msg); //5번
}
}
class MemoryException extends Exception {
MemoryException(String msg) {
super(msg);
}
}
📄 참고
자바의 정석 3rd Edition
반응형