Backend/Java

예외처리 개념

surge_95 2022. 7. 20. 19:19

프로그램 오류

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메서드의 끝

출처:자바의정석 기초편(남궁성)