일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- benchmark
- RDF
- scrum
- Python
- Knowledge Graph
- Groovy
- 노드js
- node.js
- 스크럼
- 개발자
- 예제
- C++
- 스크럼 마스터
- 파헤쳐보자
- 지식 그래프
- express
- 자바
- ngrinder
- socket.io
- 노드
- nodejs
- 특징
- 이벤트 루프
- Django
- 소켓
- node
- java
- Stream
- Router
- 스레드
- Today
- Total
라봉이의 개발 블로그
java의 정석 8강. 예외처리(하) 본문
1.7 예외의 발생과 catch 블럭
instanceof 연산자로 catch 블록의 () 안의 클래스와 비교해서 맞는 catch 블록의 {} 코드들을 실행함.
예외가 발생했을 때 생성되는 예외클래스의 인스턴스에는 발생한 예외에 대한 정보가 담겨져 있으며 다음 함수로 확인이 가능하다.
printStackTrace() - 예외발생 당시의 호출스택에 있었던 메서드의 정보와 예외 메세지를 화면에 출력
getMessage() - 발생한 예외클래스의 인스턴스에 저장된 메세지를 읽을 수 있다.
public class Main {
public static void main(String[] args) {
PrintStream ps = null;
try {
ps = new PrintStream("error.log");
System.out.println(1);
System.out.println(2);
System.out.println(3);
System.out.println(0/0); // 예외 발생
System.out.println(4);
} catch (Exception ae) {
ae.printStackTrace(ps); // 호출 스택의 내용을 화면 대신 error.log 파일에 저장
ps.println("예외 메세지: " + ae.getMessage()); // 마찬가지로 오류 메세지를 error.log 파일에 저장
}
System.out.println(6);
}
}
출력결과:
1
2
3
6
error.log:
java.lang.ArithmeticException: / by zero
at com.company.Main.main(Main.java:15)
예외 메세지: / by zero
오류 메세지의 결과를 PrintStream으로 전달하는 예제이다.
하지만 위의 PrintStream은 main 메서드 외에 다른 곳은 접근할 수가 없기 때문에 이럴 땐 'System.err'를 이용하면 된다.
public class Main {
public static void main(String[] args) {
PrintStream ps = null;
FileOutputStream fos = null;
try {
fos = new FileOutputStream("error.log", true); // error.log 파일 append를 true로 설정
ps = new PrintStream(fos);
System.setErr(ps); // err의 출력을 화면이 아닌 error.log로 변경한다.
System.out.println(1);
System.out.println(2);
System.out.println(3);
System.out.println(0/0);
System.out.println(4);
} catch (Exception ae) {
System.err.println("----------------------------");
System.err.println("예외발생시간: " + new Date());
ae.printStackTrace(System.err);
System.err.println("예외메세지: "+ ae.getMessage());
System.err.println("----------------------------");
}
System.out.println(6);
}
}
출력 결과:
1
2
3
6
error.log:
----------------------------
예외발생시간: Tue Jun 05 16:47:05 KST 2018
java.lang.ArithmeticException: / by zero
at com.company.Main.main(Main.java:19)
예외메세지: / by zero
----------------------------
System.out이나 System.err는 프로그램 어디서든 접근 가능하다.
둘 다 콘솔창 출력이 디폴트이기 때문에 SetErr 메서드로 error.log 파일로 출력을 옮긴 것이다.
1.8 finally 블럭
finally 블럭은 예외의 발생여부에 상관없이 실행되어야할 코드를 포함시킬 목적으로 한다.
try-catch-finally 순서로 구성된다.
try{
} catch(Exception e){
} finally {
// 예외의 발생여부와 관계없이 항상 수행되어야할 문장들을 넣는다.
}
try 문에서 return이 발생하여 메서드가 종료되더라도 finally문장은 실행된다.
1.9 메서드에 예외 선언하기
try-catch문 외에 예외를 메서드에 선언하는 방법이 있다.
메서드에 예외를 선언하려면, 메서드의 선언부에 키워드 throws를 사용해서 메서드 내에서 발생할 수 있는 예외를 적어두기만 하면 된다. 그리고, 예외가 여러 개일 경우에는 쉼표(,)로 구분한다.
void method() throws Exception1, Exception2, ..., ExceptionN {
// 메서드의 내용
}
선언 부분에 적어두면 다른 사람이 보았을 때 어떤 대처를 해야하는 지 이해하기 쉽기 때문에 튼튼한 코드를 만들 수 있다.
사실 예외를 메서드의 throws에 명시한다고 메서드가 처리하는 것이 아니라 그 메서드를 호출한 메서드에게 예외를 전달하여 예외처리를 떠맡기는 것이다.
public class Main {
public static void main(String[] args) throws Exception {
method1();
}
static void method1() throws Exception {
method2();
}
static void method2() throws Exception {
throw new Exception();
}
}
출력결과:
Exception in thread "main" java.lang.Exception
at com.company.Main.method2(Main.java:14)
at com.company.Main.method1(Main.java:10)
at com.company.Main.main(Main.java:6)
다음 출력 결과로 다음과 같은 사실을 알 수 있다.
예외가 발생했을 때 모두 3개의 메서드가 호출스택에 있었으며,
예외가 발생한 곳은 맨 윗줄 method2라는 것과
main 메서드가 method1()을, 그리고 method1()은 method2()를 호출했다는 것을 알 수 있다.
이렇게 예외를 넘겨줄 순 있지만 결국 어느 한 곳에서는 try-catch문으로 예외를 처리해야 한다.
1.10 예외 되던지기
한 메서드에서 발생할 수 있는 예외가 여럿인 경우, 몇 개는 try-catch문을 통해서 메서드 내에서 자체적으로 처리하고, 그 나머지는 선언부에 지정하여 호출한 메서드에서 처리하도록 함으로써, 양쪽으로 나눠서 처리되도록 할 수 있다.
이것은 예외를 처리한 후에 인위적으로 다시 발생시키는 방법을 통해서 가능한데, 이것을 '예외 되던지기'라고 한다.
public class Main {
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 블럭이 모두 수행되었음을 알 수 있다.
1.11 사용자정의 예외 만들기
사용자가 필요에 따라 프로그래머가 새로운 예외클래스를 정의하여 사용할 수 있다.
필요에 따라 알맞은 예외 클래스를 선택할 수 있다.
class MyException extends Exception {
private final int ERR_CODE; // 생성자를 통해 초기화한다.
MyException(String msg, int errCode) { // 생성자
super(msg); // 조상인 Exception 클래스의 생성자를 호출한다.
ERR_CODE = errCode;
}
MyException(String msg) {
this(msg, 100);
}
public int getErrCode() {
return ERR_CODE;
}
}
'Java > Java의 정석 읽고 정리' 카테고리의 다른 글
java의 정석 9강. java.lang 패키지(하) (0) | 2018.06.11 |
---|---|
java의 정석 9강. java.lang 패키지(상) (0) | 2018.06.11 |
java의 정석 8강. 예외처리(상) (0) | 2018.06.03 |
java의 정석 7강. 객체지향프로그래밍2(하) (0) | 2018.06.03 |
java의 정석 7강. 객체지향프로그래밍2(중) (0) | 2018.06.01 |