이 글은 자바의 정석을 읽고 개인적으로 공부한 내용을 정리한 글입니다 :>
예외 처리 exception handling
- 컴파일 에러 : 컴파일 시에 발생하는 에러
- 런타임 에러 : 실행시에 발생하는 에러
- 논리적 에러 : 실행은 되지만, 의도와 다르게 동작하는 것
- 에러 error : 프로그램 코드에 의해서 수습될 수 없는 심각한 오류
- 예외 exception : 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류
- try-catch 문
try {
// 예외가 발생한 가능성이 있는 문장들을 넣는다.
} catch (Exception1 e1) {
// Exception1이 발생했을 경우 실행할 문장을 넣는다.
} catch (Exception2 e2) {
// Exception1이 발생했을 경우 실행할 문장을 넣는다.
}
* if문과 달리, try블럭이나 catch블럭 내에 포함된 문장이 하나뿐이어도 괄호{ }를 생략할 수 없다.
예외가 발생했을 때 생성되는 예외 클래스의 인스턴스에는 발생한 예외에 대한 정보가 담겨 있으며, getMessage()와 printStackTrace()를 통해서 이 정보들을 얻을 수 있다.
- getMessage() : 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있다.
- printStackTrace() : 예외발생 당시의 호출스택(Call Stack)에 있었던 메서드의 정보와 예외 메시지를 화면에 출력한다.
catch 블럭의 괄호( )에 선언된 참조변수를 통해 이 인스턴스에 접근 할 수 있으며, 참조 변수는 선언된 catch블럭 내에서만 사용 가능하다.
try {
System.out.println(0522);
} catch (ArithmeticException ae) {
ae.printStackTrace();
// java.lang.ArtithmeticException : / by zero at ExceptionEx8.main(ExceptionEx8.java:7)
System.out.println("예외메시지 : " + ae.getMessage());
// 예외메시지 : /by zero
}
위 예시를 보면 참조변수 ae를 통해, 생성된 ArtithmeticException인스턴스에 접근할 수 있다.
- 멀티 catch 블럭
try {
...
} catch (ExceptionA | Exception B e) {
e.printStackTrace();
}
try {
...
} catch (ExceptionA e) {
e.printStackTrace();
} catch (ExceptionB e2) {
e2.printStackTrace();
}
catch 블럭을 기호 '|'를 통해 중복된 코드를 줄일 수 있다.
- 메서드에 예외 선언하기
class ExceptionEX {
public static void main(String[] args) throws Exception {
method1(); // 같은 클래스내의 static멤버이므로 객체생성없이 직접 호출가능
}
static void method1() throws Exception {
method2();
}
static void method2() throws Exception {
throw new Exception();
}
}
main 메서드가 method1()을 호출하고, method1()은 method2()를 호출했다.
예외가 발생한 곳은 method2()이다.
- try-catch-finally문
try {
...
} catch (Exception e){
// 예외처리를 위한 문장
} finally {
// 예외의 발생여부에 관계없이 항상 수행되어야하는 문장들을 넣는다.
}
예외가 발생한 경우에는 try -> catch -> finally 순으로 실행되고,
예외가 발생하지 않은 경우에는 try -> finally 순으로 실행된다.
- 자동 자원 반환 try-with-resources문
JDK1.7부터 새로 추가된 try-catch문의 변형된 버전이다.
입출력(I/O)과 관련된 클래스를 사용할 때 유용하다.
- 사용자 정의 예외 만들기
기존의 정의된 예외 클래스 외에 필요에 따라 개발자가 새로운 예외 클래스를 정의해야할 때가 있다. 보통 Exception 클래스 또는 RuntimeException클래스로부터 상속받아 사용하지만, 필요에 따라서 알맞은 예외 클래스를 선택할 수 있다.
class ExceptionEx extends Exception {
ExceptionEx(String msg) {
super(msg); // 조상인 Exception클래스의 생성자를 호출한다.
}
}
위 코드는 Exception클래스로부터 상속받아서 ExceptionEx라는 클래스를 만들었다. 필요에 따라 멤버변수나 메서드를 추가할 수 있다.
- 예외 되던지기(exception re-throwing)
예외가 발생할 가능성이 있는 메서드에서 try-catch 문을 사용해서 예외를 처리해주고 catch문에서 필요한 작업을 행한 후에 throw문을 사용해서 예외를 다시 발생시킨다. 다시 발생한 예외는 이 메서드를 호출한 메서드에게 전달되고 호출한 메서드의 try-catch문에서 예외를 또다시 처리한다.
class ExceptionEX {
public static void main(String[] args) {
try {
method1();
} catch (Exception e) {
System.out.println("main 메서드에서 예외가 처리되었습니다");
}
}
static void method1() throws Exception {
try {
throw new Exception();
} catch (Exception e) {
System.out.println("method1 메서드에서 예외가 처리되었습니다");
throw e; // 다시 예외를 발생시킴
}
}
위 코드는 method1()과 main메서드의 catch블럭이 모두 수행된다. method1()의 catch블럭에서 예외를 처리하고도 throw문을 통해 다시 예외를 발생히킨 것이다. 그리고 이 예외를 main메서드에서도 한번 더 처리하였다.
반환값이 있는 return문의 경우, catch블럭에도 return문이 있어야한다.
static int method2() {
try {
System.out.println("method2 메서드가 호출되었습니다.");
return 0;
} catch (Exception e) {
e.printStackTrace();
return 1;
} finally {
System.out.println("method2 메서드의 finally 블럭이 실행되었습니다.");
}
예외 되던지기를 통해 호출한 메서드로 예외를 전달하면, return문이 없어도 된다. 그래서 검증에서도 assert문 대신 AssertError를 생성해서 던진다.
static int method2() throws Exception { // 예외 선언
try {
System.out.println("method2가 호출되었습니다.");
return 0;
} catch (Exception e) {
e.printStackTrace();
// return 1;
throw new Exception(); // return문 대신 예외를 호출한 메서드로 전달
} finally {
System.out.println("method2 finally 블럭이 실행되었습니다.");
}
finally블럭내에도 return 문을 사용할 수 있다. try블럭이나 catch블럭의 return문 다음에 수행된다. 최종적으로 finally블럭 내의 return문의 값이 반환된다.
'뚝딱뚝딱 > Java' 카테고리의 다른 글
[Error] java.util.NoSuchElementException: No value present (0) | 2022.07.22 |
---|---|
[Java] 자바의 정석 Chapter 9 java.lang패키지와 유용한 클래스 (0) | 2022.05.23 |
[Java] 자바의 정석 Chapter6 ~ Chapter7 (0) | 2022.05.15 |
[Java] 자바의 정석 Chapter1 ~ Chapter5 (0) | 2022.05.13 |
[Java] assertThat 비교 #JUnit #Assertj (0) | 2022.01.19 |