예외처리 개념
프로그램 오류
1. 컴파일 에러
2. 런타임 에러
1) Error : 심각한 에러
2) Exception : 미약한 에러
- Exception(IO(in-out), ClassNotFound..) : 외적인 요인에 의해 발생, checked 예외
- RuntimeException(NullPoint,ClassCast..) : 프로그래머의 실수로 발생, unchecked 예외
3. 논리적 에러
try-catch문
- 예외가 발생한 catch블럭의 문장은 실행되지 않는다
- Exception(모든 예외의 최고 조상)이 선언된 catch블럭은 모든 예외 처리(마지막 catch 블럭에 와야함)
- 일치하는 catch블럭을 찾지 못하면 예외는 처리되지 못한다
class Ex8_4 {
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) {
if (ae instanceof ArithmeticException)
System.out.println("true");
System.out.println("ArithmeticException");
} catch (Exception e){ // 모든 예외처리
System.out.println("Exception");
} // try-catch의 끝
System.out.println(6);
} // main메서드의 끝
}
멀티 catch블럭 : 내용이 같은 catch블럭을 하나로 합친 것
- 부모, 자식관계는 안됨
- 공통멤버만 사용 가능
try {
...
} catch (ExceptionA | ExceptionB e){
e.printStackTrace();
}
예외 발생시키기
1. new를 이용해 예외 클래스의 객체 생성
2. throw를 이용해 예외 발생
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("프로그램이 정상 종료되었음.");
}
}
checked 예외 : Exception , unchecked 예외 : RuntimeException
- checked 예외 : 컴파일러가 예외 처리 여부를 체크(예외 처리 필수(try-catch문) 안할 경우 컴파일 에러 발생)
- unchecked 예외 : 컴파일러가 예외 처리 여부를 체크 안함(예외 처리 선택)
class Ex8_7 {
public static void main(String[] args) {
try { //Exception과 그 자손은 반드시 예외처리를 해줘야 한다(필수)
throw new Exception(); // Exception을 고의로 발생시킨다.
} catch(Exception e) {}
// RuntimeException과 그 자손은 예외처리를 해주지 않아도 컴파일이 된다.
throw new RuntimeException();
}
}
메서드에 예외 선언하기(예외 떠넘기기, 알리기)
: 메서드가 호출 시 발생가능한 예외를 호출하는 쪽에 알리는것(checked 예외만 작성)
import java.io.*;
class Ex8_10 {
public static void main(String[] args) {
try { // 예외처리
File f = createFile(""); // 예외발생
System.out.println( f.getName()+"파일이 성공적으로 생성되었습니다.");
} catch (Exception e) {
System.out.println(e.getMessage()+" 다시 입력해 주시기 바랍니다.");
}
} // main메서드의 끝
static File createFile(String fileName) throws Exception { // 예외를 작업을 시킨 main에 떠넘김(알림)
if (fileName==null || fileName.equals(""))
throw new Exception("파일이름이 유효하지 않습니다.");
File f = new File(fileName); // File클래스의 객체를 만든다.
// File객체의 createNewFile메서드를 이용해서 실제 파일을 생성한다.
f.createNewFile();
return f; // 생성된 객체의 참조를 반환한다.
} // createFile메서드의 끝
}
finally 블럭 : 예외의 발생여부에 상관없이 실행되어야 하는 코드(try-catch문 마지막에 위치)
try{
startInstall();
copyFiles();
} catch (Exception e) {
e.printStackTrace();
} finally {
deleteTempFiles(); // 프로그램 설치에 사용된 임시파일을 삭제한다
} // try-catch의 끝
사용자 정의 예외 만들기
1. 조상은 Exception과 RuntimeException 중에 선택
2. String 매개변수가 있는 생성자를 넣어주기
class MyException extends Exception {
MyException(String msg){
super(msg);
}
}
예외 되던지기(exception re-throwing)
: 예외를 처리한 후에 다시 예외를 발생시키는 것 -> throw e
(호출한 메서드와 호출된 메서드 양쪽 모두에서 예외처리하는 것)
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메서드의 끝
}
연결된 예외(chained exception)
: 한 예외가 다른 예외를 발생시킬 수 있다.
예외 A가 예외 B를 발생시키면, A는 B의 원인 예외(cause exception)
Throwable initCause(Throwable cause) // 지정한 예외를 원인 예외로 등록
Throwable getCause() // 원인 예외를 반환
when? 1. 여러 예외를 하나로 묶어서 다루기 위해서
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 { // SpaceException, MemoryException을 하나로 묶음
try {
startInstall(); // 프로그램 설치에 필요한 준비를 한다.
copyFiles(); // 파일들을 복사한다.
} catch (SpaceException e) {
InstallException ie = new InstallException("설치 중 예외발생");
ie.initCause(e);
throw ie;
} catch (MemoryException me) {
InstallException ie = new InstallException("설치 중 예외발생");
ie.initCause(me);
throw ie;
} finally {
deleteTempFiles(); // 프로그램 설치에 사용된 임시파일들을 삭제한다.
} // try의 끝
}
2. checked예외를 unchecked예외로 변경하려 할때 (try-catch문을 안쓰려고)
static void startInstall() throws SpaceException //, MemoryException {
// MemoryException은 RuntimeException으로 변경했으므로 안적어도됨
if(!enoughSpace()) { // 충분한 설치 공간이 없으면...
throw new SpaceException("설치할 공간이 부족합니다.");
}
if (!enoughMemory()) { // 충분한 메모리가 없으면...
// checked 예외를 unchecked 예외로 변경
throw new RuntimeException(new MemoryException("메모리가 부족합니다."));
}
} // startInstall메서드의 끝
출처:자바의정석 기초편(남궁성)