본문 바로가기

개발

Java - 오류 / 예외 처리하기

반응형

 

프로그램 오류
 - 컴파일 에러 (compile-time error) : 컴파일 할 때 발생하는 에러
 - 런타임 에러 (runtime error) : 실행 할 때 발생하는 에러 
   : 에러(erro) : 프로그램 코드에 의해서 수습될 수 없는 심각한 오류  > 개발자 처리할 수 없음.
   : 예외(exception) : 프로그램 코드에 의해서 수습될 수  있는 다소 미약한 오류 > 개발자가 처리 할 수 있음.
 - 논리적 에러 (logical error) : 작성 의도와 다르게 동작 

예외 클래스의 계층 구조 
 - Object - Throwable - Error - OutOfMemeryError ...
                                      - Exception - IOException / ClassNotFoundException
                                                           - RuntimeException - CalssCastException / NullPointerException ...

 Exception 클래스들 : 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외
 RuntimeExcepton 클래스들 : 프로그래머의 실수로 발생하는 예외
 

예외처리(exception handling)의 정의 
 - 프로그램 실행 시 발생 할 수 있는 예외의 발생에 대비한 코드를 작성하는 것
목적 
 - 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지하는 것

try - with - resource 문 
 - 자원의 해제를 해주는 try catch 문 

	try (BufferedReader reader = new BufferedReader(new InputStreamReader(targetUrl.openStream()))){
		StringBuffer html = new StringBuffer();
		String tmp;

		while ((tmp = reader.readLine()) != null) {
			html.append(tmp);
		}
		return html.toString();
	}

- 테스트 

public class A implements AutoCloseable {
    @Override
    public void close() throws Exception {
        System.out.println("close A ");
    }
}

public class B implements AutoCloseable {
    public B(A a){

    }
    @Override
    public void close() throws Exception {
        System.out.println("close B");
    }
}

    public static void main(String [] args) {
        try (A a = new A();
             B b = new B(a)) {

        } catch (Exception e) {

        }
    }

- 실행 결과 

 

 

 

중첩 try with resources 는 어떻게 작동할까?

자바를 이용해 외부 자원에 접근하는 경우 한가지 주의해야할 점은 외부자원을 사용한 뒤 제대로 자원을 닫아줘야한다는 점이다. public static void main(String[] args) { FileInputStream fis = null; try{ fis..

multifrontgarden.tistory.com

 

printStackTrace() 와 getMessage()
 : printStackTrace() : 예외발생 당시의 호출스택(Call Stack)에 있었던 메서드의 정보와 예외 메시지를 화면에 출력한다.
 : getMessage() : 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있다.

멀티 catch 블럭
 - 내용이 같은 catch블럭을 하나로 합친 것(JDK 1.7 부터)

try{
	...
}catch(ExceptionA | Exception B e){
	e.printStackTrace();
}

** 단 Exception 클래스가 부모 자식 간의 관계는 안된다.
  어차피 부모에서 캐치 할 수 있기때문에 같이 쓸 필요가 없다.

try{
	...
	//}catch(ParentExceptionA | ChildException B e){
}catch(ParentExceptionA e){ 
	e.printStackTrace();
}


  예외 발생시키기
 1. 연산자 new를 이용해서 밸생시키려는 예외 클래스의 객체를 만든 다음
 2. 키워드 throw를 이용해 예외를 발생시킨다.

try{
	Exception e = new Exception("고의 발생 exception");
    throw e;
    // throw new Exception("고의 발생 exception");
    
}catch(Exception e){
    System.out.println(e.getMessage());
	e.printStackTrace();
}

checked 예외, unchecked 예외
 - checked 예외 : 컴파일러가 예외 처리 여부를 체크(예외 처리 필수) >> Exception 바로 아래것들  필수사항 IOException / ClassNotFoundException 등
 - unchecked 예외 : 컴파일러가 예외 처리 여부를 체크 안함(예외 처리 선택) >> RuntimeExcdeption 아래 것들 선택 사항
 

메서드에 예외 선언하기 
 - 예외 처리 방법
   : try catch 문 
   : 예외 선언하기 (예외 떠넘기기, 알리기)
    void method() throws Exception{} >> 필수 처리만 적는다 체크드 예외만 그것이 정석!

사용자 정의 예외 만들기 
 - 우리가 직접 예외 클래스를 정의할 수 있다.
 - 조상은 Exception과 RuntimeException 중에서 선택
   Exception은 필수처리가 필요하기 때문에 try catch를 무조건 생성
   RutimeExceptin은 선택 처리 왠만하면 이걸로 하세욤

class MyException extends Exception {
	private final int ERR_CODE ; // 생성자를 통해 초기화 한다.
    
	MyException(String msg, int errCode){
    	super(msg);
        ERR_CODE = errCode;
	}
    
	MyException(String msg){
    	this(msg, 100);
	}
    
    public int getErrCode(){
    	return ERR_CODE;
    }
}


예외 되던지기(exception re-throwing)
 - 예외를 처리한 후에 다시 예외를 발생시키는 것
 - 호출한 메서드와 호출된 메서드 양쪽 모두에서 예외처리하는 것

package exception;

public class ExceptionTestMain {

    public static void main(String [] args) {

        try{
            method();
        }catch(Exception e){
            System.out.println("main 메서드에서 처리 됨.");
        }
    }

    static void method() throws Exception{
        try{
            throw new Exception();
        }catch (Exception e){
            System.out.println("method 에서 예외 처리 됨.");
            throw e;
        }
    }
}

 

연결된 예외(chained exception)
 - 한 예외가 다른 예외를 발생시킬 수 있다.
 - 예외 A가 예외 B를 발생시키면 A는 B의 원인 예외(cause exception)
 Throwable initCause(Throwable cause) : 지정한 예외를 원인 예외로 등록
 Throwable getCause() : 원인 예외를 반환

public class Throwable implements Serializable{
	...
    private Throwable cause = this;	// 객체 자신(this)를 원인 예외로 등록 
    ...
    public synchronized Throwable initCause(Throwable cause){
    	...
        	this.cause = cause; // cause를 원인 예외로 등록
            return this;
	}
    ...
    
}

예제 

void install() throws InstallException{
	try{
    	startInstall();
        copyFiles();
    } catch(SpaceException e){
    	InstallException ie = new InstallException("설치중 예외발생");
       	ie.initCause(e);	// InstallException의 원인 예외를 SpaceException으로 지정
        					// SpaceException을 InstallException의 원인으로 예외 연결 
        throw ie;	// InstallException 발생 
    }
}

연결된 예외사용 하는 이유
 1. 여러 예외를 하나로 묶어서 다루기 위해서
 2. checked예외를 unchecked예외로 변경하려 할 때

반응형

'개발' 카테고리의 다른 글

Java - String 클래스  (0) 2021.06.05
Java - Object 클래스  (0) 2021.06.05
Java - 내부 클래스(inner class) / 익명 클래스(anonymous class)  (0) 2021.06.05
Java - 인터페이스  (0) 2021.06.05
Java - 추상클래스  (0) 2021.06.05