[JAVA] 예외처리

Ming·2022년 9월 28일
0

자바

목록 보기
8/14

예외처리

프로그램 오류

  • 컴파일 에러 : 컴파일 할 때 발생하는 에러
  • 런타임 에러 : 실행할 때 발생하는 에러
  • 논리적 에러 : 작성 의도와 다르게 동작

Java의 런타임 에러

  • 에러(error) : 프로그램 코드에 의해서 수습될 수 없는 심각한 오류
  • 예외(exception) : 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류
    ➡️ 에러는 어쩔 수 없지만, 예외는 처리하자.

예외처리

예외처리는 프로그램 실행 시 발생할 수 있는 예외의 발생에 대비한 코드를 작성하는 것으로 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지하기 위해 예외처리가 필요하다.

Exception과 RuntimeException

  • Exception 클래스 : 사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외
    IOException(입출력 예외), ClassNotFoundException(클래스가 존재하지 않을 때) ...
  • RuntimeException 클래스 : 프로그래머의 실수로 발생하는 예외
    ArithmeticException(산술계산 예외), ClassCastException(형변환 예외), NullPointerException(널 포인터), IndexOutOfBoundsException(배열 범위 벗어남) ...

예외 처리하기(try-catch 문)

try{
	//예외가 발생할 가능성이 있는 문장
}catch(Exception1 e1){
	//Exception1이 발생했을 경우, 이를 처리하기 위한 문장
}catch(Exception2 e2){
	//Exception2가 발생했을 경우 이를 처리하기 위한 문장
}finally{
	//예외 발생여부에 관계없이 항상 수행되어야하는 문장
    //try-catch문의 맨 마지막에 위치
}
  • try블럭 내에서 예외가 발생한 경우, 발생한 예외와 일치하는 catch 블럭이 있는지 확인한다. 일치하는 catch블럭을 찾게 되면, 그 catch 블럭 내의 문장들을 수행하고 전체 try-catch문을 빠져나가서 그 다음 문장을 계속해서 수행한다. 일치하는 catch블럭을 찾지 못하면 예외 처리가 되지 않는다.
  • try블럭 내에서 예외가 발생하지 않은 경우는 catch블럭을 거치지 않고 전체 try-catch문을 빠져나가서 수행된다.
  • finally 블럭 : 예외 발생여부와 관계없이 수행되는 블럭으로 try 블럭 안에 return 문이 있어서 try 블럭을 벗어날 때도 finally 블럭이 실행된다.

💡 Exception e
모든 예외의 최고조상이기 때문에 모든 예외를 처리할 수 있다. 그렇기 때문에 Exception e가 선언된 catch 블럭은 제일 마지막에 와야한다. (위에 있으면 아래 예외블럭을 처리하지 못한다)

Exception 에러 출력

try 블럭에서 예외가 발생하면 예외 객체가 생성된다. 이 객체에 발생한 예외에 대한 정보가 들어있고 printStackTrace(), getMessage() 등의 메서드를 갖는다.

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

예외 발생시키기

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

public static void main(String args[]) {
	try {
    	Exception e = new Exception("에러 발생");
		throw e;
    } catch (Exception e) {
    	System.out.println("에러 메시지 : " + e.getMessage());
        e.printStackTrace();
    }
}

checked예외와 unchecked 예외

  • checked예외 : 컴파일러가 예외 처리 여부를 체크(예외 처리 필수)
    Exception과 그 자손들
    public static void main(String[] args) {
    	throw new Exception();
    }
    try-catch문을 이용해 예외처리를 해주어야하는데 하지 않았기 때문에 컴파일 오류가 발생한다. 즉, Exception 예외는 예외 처리를 필수로 해야하기 때문에 checked 예외라는 의미이다.
  • unchecked예외 : 컴파일러가 예외 처리 여부를 체크 안함(예외 처리 선택)
    RuntimeException과 그 자손들
    public static void main(String [] args) {
    	throw new RuntimeException();
    }
    RuntimeExcepton은 unchecked 예외이기 때문에 예외 처리가 선택적이므로 try-catch문이 없어도 컴파일 에러가 발생하지 않고 예외가 발생했다는 결과가 출력된다.

throws

예외 선언하기는 throws키워드를 사용하고 메서드가 호출 시 발생가능한 예외를 호출하는 쪽에 알리는 것이다.

void method() throws Exception1, Exception2, ... ExceptionN }
	//메서드의 내용
}
void method() throws Exception {
	//메서드의 내용
}

💡 main 함수에 throws 를 사용한 경우
main함수에서 예외처리가 발생하면 try-catch문 없어서 비정상종된다. 그리고 JVM에게 예외를 맡기게 된다.

사용자 정의 예외 만들기

직접 예외 클래스를 정의할 수 있다. 조상은 Exception과 RuntimeException 중에서 선택하고 생성자를 작성해주어야한다.

class MyException extends Exception{
	MyException(String msg) { //문자열을 매개변수로 받는 생성자
		super(msg); //조상인 Exception클래스의 생성자를 호출
	}
}

💡 Exception은 필수 처리 예외이기 때문에 반드시 try-catch문을 써야하고 RuntimeException은 선택 처리 예외이기 때문에 try-catch문을 사용하지 않아도 된다. 그렇기 때문에 가능하면 선택처리가 가능한 RuntimeException을 사용하는게 좋다.

예외 되던지기

예외 되던지기는 예외를 처리한 후에 다시 예외를 발생시키는 것을 의미한다. 즉, 호출한 메서드와 호출된 메서드 양쪽 모두에서 예외를 처리하게 된다.

public static void main(String[] args) {
	try {
		method1();
	} catch (Exception e) {
		System.out.println("main 메서드에서 예외가 처리되었습니다.");
	}
}
static void method1() throws Exception {
	try {
		throw new Exception();
	} catch (Exception e) {
		System.out.println("method1메서드에서 예외가 처리되었습니다.);
		throw e; //다시 예외를 발생시킨다.
	}
}
/*결과
method1메서드에서 예외가 처리되었니다.
main 메서드에서 예외가 처리되었습니다.
*/

method1()에서 try-catch문으로 예외를 처리하고 난 다음에 throw e를 통해 다시 예외를 발생시킨다. 그렇게 되면 method1()을 호출한 main함수로 예외가 전달된다. 이렇게 호출한 메서드와 호출된 메서드 양쪽에서 모두 예외 처리하게 된다.


[출처]
자바의 정석 - https://www.youtube.com/playlist?list=PLW2UjW795-f6xWA2_MUhEVgPauhGl3xIp

0개의 댓글