<예제 8-1 >
✍️ 입력
class Ex8_1 {
public static void main(String args[]) {
System.out.println(1);
try {
System.out.println(2);
System.out.println(3);
} catch (Exception e) {
System.out.println(4); // 실행되지 않는다.
} // try-catch의 끝
System.out.println(5);
}
}
💻 출력
1
2
3
5
<예제 8-2 >
✍️ 입력
class Ex8_2 {
public static void main(String args[]) {
System.out.println(1);
try {
System.out.println(0/0);
System.out.println(2); // 실행되지 않는다.
} catch (ArithmeticException ae) {
System.out.println(3);
} // try-catch의 끝
System.out.println(4);
} // main메서드의 끝
}
💻 출력
1
3
4
<예제 8-3 >
✍️ 입력
class Ex8_3 {
public static void main(String args[]) {
System.out.println(1);
System.out.println(2);
try {
System.out.println(3);
System.out.println(0/0);
System.out.println(4); // 실행되지 않는다.
} catch (Exception e){ // ArithmeticException대신 Exception을 사용.
System.out.println(5);
} // try-catch의 끝
System.out.println(6);
} // main메서드의 끝
}
💻 출력
1
2
3
5
6
<예제 8-5 >
✍️ 입력
class Ex8_5 {
public static void main(String args[]) {
System.out.println(1);
System.out.println(2);
try {
System.out.println(3);
System.out.println(0/0); // 예외발생!!!
System.out.println(4); // 실행되지 않는다.
} catch (ArithmeticException ae) {
ae.printStackTrace();
System.out.println("예외메시지 : " + ae.getMessage());
} // try-catch의 끝
System.out.println(6);
} // main메서드의 끝
}
💻 출력
1
2
3
java.lang.ArithmeticException: / by zero
예외메시지 : / by zero
6
at Ex8_5.main(Ex8_5.java:8)
-> 예외가 발생했을 때 생성되는 예외 클래스의 인스턴스에는 발생한 예외에 대한 정보가 담겨 있으며 예외 메서드를 통해 정보드를 얻을 수 있다.
JDK 1.7부터 여러 catch블럭을 '|'으로 합칠 수 있게 되었다.
두 예외 클래스가 조상과 자손의 관계에 있다면, 그냥 조상 클래스만 써주는 것과 똑같기 때문에 에러발생한다.
-> 예외객체의 메서드는 조상의 메서드만 사용 가능하다(공통부분만 사용가능하다) 만약, 자식의 메서드를 사용하고 싶다면 if-else문과 instanceof로 확인 후 형변환 해서 자식의 메서드를 호출한다.
try{
...
} catch (ExceptionA | ExceptionB e)
e.methodA(); //에러. ExceptionA 선언된 methodA()는 호출불가
if(e instanceof ExceptionA) {
ExceptionA e1 = (ExceptionA)e;
e1.methodA();
} else { // if (e instanceof ExceptionB)
...
-> 예외 A, B가 상관없는 관계일 때 다음과 같이 해결 할 수도 있다.
<예제 8-6 >
✍️ 입력
class Ex8_6 {
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 Ex8_6.main(Ex8_6.java:4)
-> Exception인스턴스를 생성할 때, 생성자에 String을 넣어 주면, 이 String이 Exception인스턴스에 메시지로 저장된다. 이는 getMessage()를 이용해 얻을 수 있다.
<예제 8-7 >
✍️ 입력
class Ex8_7 {
public static void main(String[] args) {
throw new Exception(); // Exception을 고의로 발생시킨다.
}
}
💻 출력
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Unhandled exception type Exception
at Ex8_7.main(Ex8_7.java:3)
-> 컴파일 하면, 위와 같은 에러가 발생하며 컴파일이 완료되지 않는다. 예외처리가 되어 있지 않다는 에러이다.
-> 'Exception클래스와 그 자손들(checked예외)'가 발생 할 경우 예외처리를 해주지 않으면 컴파일조차 되지 않는다.
<예제 8-8 >
✍️ 입력
class Ex8_8 {
public static void main(String[] args) {
throw new RuntimeException(); // RuntimeException을 고의로 발생시킨다.
}
}
💻 출력
Exception in thread "main" java.lang.RuntimeException
at Ex8_8.main(Ex8_8.java:3)
-> 성공적으로 컴파일은 되지만, RuntimeException이 발생하여 비정상적으로 종료될 것이다.
-> 'RuntimeException클래스과 그 자손(unchecked예외)'에 해당하는 예외는 프로그래머가 실수로 발생하는 것들이기 때문에 예외처리를 강제하지 않는다.
-> interrupterException은 Exception(checked)의 자식이므로 예외처리를 꼭 해주어야 한다.
-> lllegalMonitorStateException은 RuntimeException(unchecked)의 자식이므로 예외처리 생략 가능!
<예제 8-9 >
✍️ 입력
class Ex8_9 {
public static void main(String[] args) throws Exception {
method1(); // 같은 클래스내의 static멤버이므로 객체생성없이 직접 호출가능.
} // main메서드의 끝
static void method1() throws Exception {
method2();
} // method1의 끝
static void method2() throws Exception {
throw new Exception();
} // method2의 끝
}
💻 출력
Exception in thread "main" java.lang.Exception
at Ex8_9.method2(Ex8_9.java:11)
at Ex8_9.method1(Ex8_9.java:7)
at Ex8_9.main(Ex8_9.java:3)
<예제 8-10 >
✍️ 입력
import java.io.*;
class Ex8_10 {
public static void main(String[] args) {
try {
File f = createFile("test.txt");
System.out.println( f.getName()+"파일이 성공적으로 생성되었습니다.");
} catch (Exception e) {
System.out.println(e.getMessage()+" 다시 입력해 주시기 바랍니다.");
}
} // main메서드의 끝
static File createFile(String fileName) throws Exception {
if (fileName==null || fileName.equals(""))
throw new Exception("파일이름이 유효하지 않습니다.");
File f = new File(fileName); // File클래스의 객체를 만든다.
// File객체의 createNewFile메서드를 이용해서 실제 파일을 생성한다.
f.createNewFile();
return f; // 생성된 객체의 참조를 반환한다.
} // createFile메서드의 끝
} // 클래스의 끝
💻 출력
test.txt파일이 성공적으로 생성되었습니다.
-> 중복된 코드를 줄일 수 있다.
<예제 8-11 >
✍️ 입력
class Ex8_11 {
public static void main(String args[]) {
try {
startInstall(); // 프로그램 설치에 필요한 준비를 한다.
copyFiles(); // 파일들을 복사한다.
} catch (SpaceException e) {
System.out.println("에러 메시지 : " + e.getMessage());
e.printStackTrace();
System.out.println("공간을 확보한 후에 다시 설치하시기 바랍니다.");
} catch (MemoryException me) {
System.out.println("에러 메시지 : " + me.getMessage());
me.printStackTrace();
System.gc(); // Garbage Collection을 수행하여 메모리를 늘려준다.
System.out.println("다시 설치를 시도하세요.");
} finally {
deleteTempFiles(); // 프로그램 설치에 사용된 임시파일들을 삭제한다.
} // try의 끝
} // main의 끝
static void startInstall() throws SpaceException, MemoryException {
if(!enoughSpace()) // 충분한 설치 공간이 없으면...
throw new SpaceException("설치할 공간이 부족합니다.");
if (!enoughMemory()) // 충분한 메모리가 없으면...
throw new MemoryException("메모리가 부족합니다.");
} // startInstall메서드의 끝
static void copyFiles() { /* 파일들을 복사하는 코드를 적는다. */ }
static void deleteTempFiles() { /* 임시파일들을 삭제하는 코드를 적는다.*/ }
static boolean enoughSpace() {
// 설치하는데 필요한 공간이 있는지 확인하는 코드를 적는다.
return false;
}
static boolean enoughMemory() {
// 설치하는데 필요한 메모리공간이 있는지 확인하는 코드를 적는다.
return true;
}
} // ExceptionTest클래스의 끝
class SpaceException extends Exception {
SpaceException(String msg) {
super(msg);
}
}
class MemoryException extends Exception {
MemoryException(String msg) {
super(msg);
}
}
💻 출력
에러 메시지 : 설치할 공간이 부족합니다.
공간을 확보한 후에 다시 설치하시기 바랍니다.
SpaceException: 설치할 공간이 부족합니다.
at Ex8_11.startInstall(Ex8_11.java:22)
at Ex8_11.main(Ex8_11.java:4)
<예제 8-12 >
✍️ 입력
class Ex8_12 {
public static void main(String[] args) {
try {
method1();
} catch (Exception e) {
System.out.println("main메서드에서 예외가 처리되었습니다.");
}
} // main메서드의 끝
static void method1() throws Exception {
try {
throw new Exception();
} catch (Exception e) {
System.out.println("method1메서드에서 예외가 처리되었습니다.");
throw e; // 다시 예외를 발생시킨다.
}
} // method1메서드의 끝
}
💻 출력
method1메서드에서 예외가 처리되었습니다.
main메서드에서 예외가 처리되었습니다.
예외 A가 예외 B를 발생시켰다면, A를 B의 '원인 예외(cause exception)'라고 한다.
왜 사용할까?
여러가지 예외를 하나의 큰 분류의 예외로 묶어서 다루기 위함이다.
checked <-> unchecked 바꿀 수 있다.
<예제 8-13 >
✍️ 입력
class Ex8_13 {
public static void main(String args[]) {
try {
install();
} catch(InstallException e) {
e.printStackTrace();
} catch(Exception e) {
e.printStackTrace();
}
} // main의 끝
static void install() throws InstallException {
try {
startInstall(); // 프로그램 설치에 필요한 준비를 한다.
copyFiles(); // 파일들을 복사한다.
} catch (SpaceException2 e) {
InstallException ie = new InstallException("설치 중 예외발생");
ie.initCause(e);
throw ie;
} catch (MemoryException2 me) {
InstallException ie = new InstallException("설치 중 예외발생");
ie.initCause(me);
throw ie;
} finally {
deleteTempFiles(); // 프로그램 설치에 사용된 임시파일들을 삭제한다.
} // try의 끝
}
static void startInstall() throws SpaceException2, MemoryException2 {
if(!enoughSpace()) { // 충분한 설치 공간이 없으면...
throw new SpaceException2("설치할 공간이 부족합니다.");
}
if (!enoughMemory()) { // 충분한 메모리가 없으면...
throw new MemoryException2("메모리가 부족합니다.");
// throw new RuntimeException(new MemoryException("메모리가 부족합니다."));
}
} // startInstall메서드의 끝
static void copyFiles() { /* 파일들을 복사하는 코드를 적는다. */ }
static void deleteTempFiles() { /* 임시파일들을 삭제하는 코드를 적는다.*/ }
static boolean enoughSpace() {
// 설치하는데 필요한 공간이 있는지 확인하는 코드를 적는다.
return false;
}
static boolean enoughMemory() {
// 설치하는데 필요한 메모리공간이 있는지 확인하는 코드를 적는다.
return true;
}
} // ExceptionTest클래스의 끝
class InstallException extends Exception {
InstallException(String msg) {
super(msg);
}
}
class SpaceException2 extends Exception {
SpaceException2(String msg) {
super(msg);
}
}
class MemoryException2 extends Exception {
MemoryException2(String msg) {
super(msg);
}
}
💻 출력
InstallException: 설치 중 예외발생
at Ex8_13.install(Ex8_13.java:17)
at Ex8_13.main(Ex8_13.java:4)
Caused by: SpaceException2: 설치할 공간이 부족합니다.
at Ex8_13.startInstall(Ex8_13.java:31)
at Ex8_13.install(Ex8_13.java:14)
... 1 more
(정리)
[출처] 자바의 정석 <기초편> (남궁 성 지음)