public static void main(String[] args) throws Exception{
method1();
}
private static void method1() throws Exception{
method2();
}
private static void method2() throws Exception{
throw new Exception();
}
메인 메서드에서 Exception을 throws 한다는 것은 반드시 처리해야하는 Exception이라는 의미이다.
예외를 전달받은 메서드가 예외를 처리하지 못하면 자신을 호출한 메서드(호출스택에 있는 메서드)를 따라 전달되다가 제일 마지막에 위치한 main메서드로 예외를 전달하고,
main메서드도 예외를 처리하지 못하면,
main메서드까지 종료되며 프로그램이 종료된다.
위 코드를 실행결과를 통해 다음과 같은 사실을 파악할 수 있다.
예외 발생 후
method2, method1, main 메서드가 호출(스택)되었으며,
예외가 발생한 곳은 method2 부터 method1, main 순이다.
method2가 의도적으로 발생시킨 예외는 try catch문을 통해 처리하지 않았으므로 예외가 자신을 호출한 method1에게 전달된다.
method1도 마찬가지로 예외처리를 해주지 않았으므로 main메서드에 예외를 넘겨주며
마지막으로 예외를 넘겨받은 main메서드도 처리할 방법이 선언되지 않았으므로 강제 종료된다.
예외가 발생한 메서드에서 처리를 하지 않고 throw로 자신을 호출한 메서드에 예외를 넘기면
해당 예외를 넘겨받은 메서드에서 처리를 해줘야한다.
public static void main(String[] args) {
method1();
}
static void method1() {
try {
throw new Exception(); // 임의로 예외 발생
}catch(Exception e) { // Exception 타입의 참조변수 e 선언
System.out.println("예외가 처리됨"); // 예외처리 시 출력될 문구
e.printStackTrace(); // 예외에 대한 정보를 화면에 출력하는 메서드
}
}
try문에서 임의로 예외를 발생시키고,
catch문을 통해 예외에 대한 처리를 진행한다.
public static void main(String[] args) {
try {
method1();
} catch (Exception e) { // 예외 캐치
System.out.println("main 메서드에서 예외가 처리됨");
e.printStackTrace(); // 에러 메시지 출력
}
}
private static void method1() throws Exception{
throw new Exception(); // 임의로 에러 발생
}
예시코드 2와 예시코드 3은 둘 다 method1에서 예외가 발생한다.
하지만 처리방법은 상이하다.
예시코드 2는 main메서드가 method1을 호출하고 method1은 본인의 영역 내에서 자체적으로 예외를 처리하기 때문에 main메서드는 예외발생 여부를 알 턱이 없다.
반면
예시코드3에서 method1은 throws를 통해 자신을 호출한 메서드로 예외를 넘겨준다.
예외를 넘겨받은 main메서드는 예외와 일치하는 catch문을 실행시킨다.
처리방법은 그때그때 상황에 맞게 사용하자.
import java.io.File;
public class ExceptionEX16 {
public static void main(String[] args) {
try {
File f = createFile(""); // 얘기 정상적으로 실행되어야 밑 syso코드가 실행된다. 예외가 발생하면 바로 catch블록으로 간다.
System.out.println(f.getName()+"파일이 성공적으로 생성되었습니다.");
} catch (Exception e) {
e.getStackTrace();
System.out.println(e.getMessage()+"파일명을 다시 입력하세요.");
}
}
static File createFile (String fileName) throws Exception{
if(fileName == null || fileName.equals("")) { // 파일 이름이 null값이거나 공백이면
throw new Exception("파일이 유요하지 않습니다.");
}
File f = new File(fileName); // File클래스의 객체 생성
f.createNewFile(); // File 객체의 createNewfile 메서드를 이용하여 실제 파일 생성
return f;
}
}
위 코드는 main메서드가 createFile메서드로부터 예외를 넘겨받아 자체적으로 처리하는 코드이다.
예시코드를 치며 문득 든 생각은
"메인메서드의 try부분의 첫코드에서 메서드를 받아 처리하면 더 다채로운 예외처리는 하지 못할 것 같다." 라고 생각했는데 내 생각이 틀렸다.
오히려 main메서드의 try구분에서 다른 메서드들을 넘겨받아, 메서드를 하나씩 실행시켜가면서 예외를 파악하는 편이 객체지향적이라고 느꼈다.