예외 발생시키기
예외 발생시키기 -> 키워드 throw를 사용해서 프로그래머가 고의로 예외를 발생!
1. 연산자 new를 이용해서 발생시키려는 예외클래스의 객체를 만든 다음
Exception e = new Exception(“고의로 발생시켰음”);
2. 키워드 throw를 이용해서 예외를 발생시킨다.
예제1) throw를 사용해서 고의로 예외를 발생시키는 프로그램
public class ExceptionTest2 {
public static void main(String[] args) {
try {
Exception e = new Exception("고의로 발생시켰음");
throw e; // 예외를 발생시겼음
//throw new Exception("고의로 발생시켰음") -> 위의 두줄을 한줄로
} catch (Exception e ) {
System.out.println("에러 메시지: " + e.getMessage());
e.printStackTrace();
}
System.out.println("프로그램이 정상 종료되었음");
}
}
<출력값>
에러 메시지: 고의로 발생시켰음
java.lang.Exception: 고의로 발생시켰음
at ExceptionTest2.main(ExceptionTest2.java:9)
프로그램이 정상 종료되었음
-> Exception인스턴스를 생성할 때, 생성자에 String을 넣어주면, 이 String이 Exception 인스턴스에 메시지로 저장된다. 이 메시지는 getMessage( )를 이용해서 얻을 수 있다!
자바 예외 구문 checked 예외, unchecked예외
- checked예외: 컴파일러가 예외 처리 여부를 체크(예외 처리 필수) (Exception과 자손들)
- unchecked예외: 컴파일러가 예외 처리 여부를 체크 안 함(예외 처리 선택) (RuntimeException과 자손들)
- checked예외는 필수 처리!! (try-catch문 필수)
- unchecked예외는 try-catch문 없이 throw만으로 사용 가능 -> 컴파일은 성공했지만 비정상 종료(try-catch문 선택)
throw new Exception(); // Exception을 고의로 발생시킴(컴파일 불가 try-catch문의 부재)
throw new RuntimeException(); // RuntimeException을 고의 발생시킴(컴파일 가능, 하지만 비정상적인 종료)
try { // Exception과 그 자손은 반드시 예외처리를 해줘야 한다.
throw new Exception();
} catch(Exception e) {
}
try {
throw new RuntimeException();
} catch(Exception e) {
}
throw new Exception으로 예외가 발생했지만 밑의 catch(Exception e) 구문으로 예외처리되었다.
두 번째 try구문으로 들어가면서 throw new RuntimeException으로 예외가 발생했지만 밑에 catch(Exception e) 구문으로 예외처리되었다.
메서드에 예외 선언하기
<예외를 처리하는 방법>
(1) try-catch문(직접 처리), (2) 예외 선언하기(예외 떠넘기기)
- 예외 선언하기: 메서드가 호출 시 발생 가능한 예외를 호출하는 쪽에 알리는 것(예외를 떠넘기는 것이고 처리하는 것이 아님) -> main 메서드까지 예외처리가 안된다면 비정상적으로 종료!
- 메서드의 예외 선언하기(메서드의 선언부에 키워드 throws를 사용해서 메서드 내에서 발생할 수 있는 예외를 적어주면 되고, 여러 개일 경우 쉼표로 구분)
-> 예외를 발생시키는 키워드 throw와 예외를 메서드에 선언할 때 쓰이는 throws 잘 구분하기!!!!
- 예외선언은 Exception 자손만! RuntimeException 선언해도 되기는 하는데 보통 안 함
-> 만일 예외의 최고조 상인 Exception클래스를 메서드에 선언하면 이 메서드는 모든 종류의 예외가 발생할 가능성이 있다는 뜻!
static void startInstall() throws SpaceException, MemoryException {
if(!enoughSpace()) // 충분한 설치공간이 없으면..
throw new SpaceException("설치할 공간이 부족합니다.");
if(!engouhMemory())
thrwo new MemoryException("메모리가 부족합니다.");
} // startInstall메서드의 끝
-> startInstall 메서드를 호출하면 SpaceException와 MemoryException 예외가 발생할 수 있다는 것을 선언부에 적음!
-> StartInstall 메서드를 호출한 메서드가 또다시 자신을 호출한 메서드에게 전달하거나 예외처리를 할 수 있음!
-> 이런식으로 계속 호출스택에 있는 메서드들을 따라 전달되다가 main메서드에서도 예외처리가 되지 않으면, main메서드마저 종료되어 프로그램 전체가 비정상 종료됨!
예제1) 메서드의 예외 선언 흐름
public class ExceptionTest3 {
public static void main(String[] args) throws Exception {
method1(); // 같은 클래스 내의 static 멤버이므로 객체생성없이 직접 호출가능
} // main메서드의 끝
static void method1() throws Exception { //try-catch구문이 없어서 예외처리 실패
method2();
} // method1()의 끝
static void method2() throws Exception { // try-catch구문이 없어서 예외처리 실패
throw new Exception();
} // method2()의 끝
}
(1) main 메서드가 method1 호출
(2) method1이 method2호출 -> method2에서 예외 발생, 처리 하지 못함(try-catch구문이 없어서)
(3) 예외를 method2 -> method1 에게 떠넘김(선언)
(4) method1 예외 처리 하지 못함(try-catch구문이 없어서) ->
(5) 예외를 method1 -> main 메서드에게 떠넘김(선언)
(6) main메서드도 예외를 처리하지 못함(try-catch구문이 없어서)
(7) mian메서드가 종료가 되고 프로그램이 비정상 종료되면서 예외는 JVM(자바버추얼머신)한테 가게됨
<출력결과>
Exception in thread "main" java.lang.RuntimeException
at ExceptionTest3.method2(ExceptionTest3.java:13)
at ExceptionTest3.method1(ExceptionTest3.java:9)
at ExceptionTest3.main(ExceptionTest3.java:5)
-> 예외가 발생한 당시의 호출스택의 상황을 보여주고 있음
1) 예외가 발생했을 때, 모두 3개의 메서드(main, method2, method1)가 호출스택에 있었음
2) 예외가 발생한 곳은 제일 윗줄에 있는 method2( ), 13번째 줄라는 것
3) main메서드가 method1( )을, method1은 method2( )를 호출했다는 것을 알 수 있음(아래서부터 위로)
예제2) 메서드의 예외선언하기
1) main메서드에서 try-catch구문 사용하기
(method1이 예외선언하고 main메서드가 예외처리(try-catch문으로!)
public class FinallyTest3 {
public static void main(String[] args) {
try {
method1(); // java:6 (3)
} catch (Exception e) {
System.out.println("main메서드에서 예외가 처리되었습니다. "); // (1)
e.printStackTrace();
}
} // main메서드의 끝
static void method1() throws Exception {
throw new Exception("method에서 예외가 발생했습니다."); // java:14 (2)
} // method1의 끝
} // class의 끝
<출력값>
main메서드에서 예외가 처리되었습니다.
java.lang.Exception: method에서 예외가 발생했습니다.
at FinallyTest3.method1(FinallyTest3.java:14)
at FinallyTest3.main(FinallyTest3.java:6)
(1) 예외처리 완료된 catch구문부터 출력!(main 메서드에)
(2) 예외 발생된 곳 출력 (throw new Exception("method에서 예외가 발생했습니다."))
(3) 예외 사항이 있는 메서드를 호출한 곳! main메서드에서 method1( );
2) method1 메서드(자기자신이 직접)에서 try-catch구문 사용하기(예외처리하기)
public class FinallyTest3 {
public static void main(String[] args) {
method1();
}
static void method1() {
try {
throw new Exception("method1에서 예외 발생했습니다.");
} catch ( Exception e ) {
System.out.println("method1에서 예외 처리되었습니다.");
System.out.println("끝!"); //
}
}
}
<출력값>
method1에서 예외 처리되었습니다.
끝!
-> method1( )이 직접 예외처리하기 때문에 메서드 선언부에 throws를 안적어도 된다.
-> 예외가 method1( )에서 발생했지만 catch구문에서 예외처리 되었다!
Finally블럭
- 예외 발생여부와 관계없이 수행되어야 하는 코드 작성
-> 예외가 발생한 경우 ‘try -> catch -> finally’ 의 순으로 실행. 예외가 발생하지 않은 경우 ‘try -> finally’ 의 순으로 실행
예제1) Finally블록을 사용하지 않고 프로그램 작성(코드의 중복 생김)
public class FinallyTest {
public static void main(String[] args) {
try {
startInstall(); // 프로그램설치에 필요한 준비하기
copyFiles(); // 파일들 복사
deleteTempFiles(); // 프로그램 설치에 사용된 임시파일 삭제
} catch ( Exception e ) {
e.printStackTrace();
deleteTempFiles(); // 프로그램 설치에 사용된 임시파일 삭제
} // try-catch의 끝
} // main의 끝
static void startInstall() {
/* 프로그램 설치에 필요한 준비를 하는 코드 */
}
static void copyFiles() { /* 파일을 복사하는 코드 */}
static void deleteTempFiles() { /* 파일을 삭제하는 코드 */ }
}
예제2) Finally블록을 사용하고 프로그램 작성
try {
startInstall(); // 프로그램설치에 필요한 준비하기
copyFiles(); // 파일들 복사
} catch ( Exception e ) {
e.printStackTrace();
} finally {
deleteTempFiles(); // 프로그램 설치에 사용된 임시파일 삭제
} // try-catch의 끝
} // main의 끝
-> 예제1과 예제2 나머지는 다 동일하고 중복되는 코드를 삭제하고 finally 블록을 추가해준다!
예제3) method1을 호출하면서 흐름 이해하기
public class FinallyTest3 {
public static void main(String[] args) {
// method1은 static 메서드여서 객체 없이 사용 가능
FinallyTest3.method1(); // method1을 호출
System.out.println("method1()의 수행을 마치고 main메서드로 돌아왔습니다.");
}
static void method1() {
try {
System.out.println("method1()이 호출되었습니다.");
return; // 현재 실행 중인 메서드를 종료
} catch ( Exception e ) {
e.printStackTrace();
} finally {
System.out.println("method1()의 finally블럭이 실행되었습니다.");
}
}
}
<출력 값>
method1()이 호출되었습니다.
method1()의 finally블럭이 실행되었습니다.
method1()의 수행을 마치고 main메서드로 돌아왔습니다.
-> method1이 호출되고 “method1()이 호출되었습니다”이 출력되면서 반환됨. 에러가 있다면 catch로 들어가서 e.printStackTrac()를 출력하겠지만,여기서는 예외가 없고 반환되면서 바로 finally 구문으로 넘어가서 출력된다!
'멀티캠퍼스 풀스택 과정 > Java의 정석' 카테고리의 다른 글
자바의 정석6-1 Java.lang패키지, eqauls, hasecode, toString (0) | 2022.01.07 |
---|---|
자바의 정석5-3 사용자 정의 예외, 예외 되던지기, 연결된 예외 (0) | 2022.01.06 |
자바의 정석5-1 예외처리(exception handling) (0) | 2022.01.06 |
자바의 정석4-3 내부클래스와 익명클래스 (0) | 2022.01.06 |
자바의 정석4-2 인터페이스(interface), 디폴트와 static 메서드 (0) | 2022.01.05 |