[자바/Java] 예외처리란?

resilient

·

2021. 1. 15. 12:47

728x90
반응형

 

github.com/whiteship/live-study/issues/9

 

9주차 과제: 예외 처리 · Issue #9 · whiteship/live-study

목표 자바의 예외 처리에 대해 학습하세요. 학습할 것 (필수) 자바에서 예외 처리 방법 (try, catch, throw, throws, finally) 자바가 제공하는 예외 계층 구조 Exception과 Error의 차이는? RuntimeException과 RE가

github.com

목표

자바의 예외 처리에 대해 학습하세요.

학습할 것 (필수)

  • 자바에서 예외 처리 방법 (try, catch, throw, throws, finally)
  • 자바가 제공하는 예외 계층 구조
  • Exception과 Error의 차이는?
  • RuntimeException과 RE가 아닌 것의 차이는?
  • 커스텀한 예외 만드는 방법

마감일시

2021년 1월 16일 토요일 오후 1시까지.


#자바에서 예외 처리 문 -try-catch문

try {
	//예외가 발생할 가능성이 있는 문장들을 넣는다.
}catch(Exception1 e1) {
	//Exception1이 발생했을 경우 이를 처리하기 위한 문장.
}catch(Exception2 e2) {
	//Exception2이 발생했을 경우 이를 처리하기 위한 문장.
}catch(Exception3 e3) {
	//Exception3이 발생했을 경우 이를 처리하기 위한 문장.
}

하나의 try블럭 다음에는 여러 종류의 예외를 처리할 수 있도록 하나 이상의 catch 문이 올 수 있고, 발생한 예외의 종류와 일치하는 catch블럭이 없으면 예외는 처리되지 않는다.

public class Main {

	public static void main(String[] args) {
		int number = 100;
		int result = 0;
		
		for(int i =0;i<10;i++) {
			try {
				result = number /  (int)(Math.random()*10);
				System.out.println(result);
			} catch (ArithmeticException e) {
//ArithmeticException 은 산술연산과정에서 정수가 0으로 나누는 것이 안되기 때문에 발생하는 오류이다.
				System.out.println("0");
			}
		}
	}
}

만약에 try 블럭내에서 예외가 발생하지 않으면 catch 블럭을 아예 거치지 않고 try-catch문을 빠져나오고

예외가 발생하면 발생한 예외와 일치하는 catch블럭이 있는지 확인한다. 일치하는 catch 블럭을 찾게 되면 그 블럭내의 문장들을 수행하고 try-catch 문을 빠져나가서 다음 문장들을 계속해서 수행한다. 

하지만 catch블럭의 예외와 try블럭내에서 발생한 예외가 다르면 catch블럭은 처리되지 못한다.

 

#throw 키워드

 

throw 키워드를  이용해서 개발자가 고의적으로 예외를 만들 수 있다.

1. 먼저 연산자 new를 이용해서 발생시키려는 예외 클래스의 객체를 만들어준다.
		
        Exception e = new Exception("고의로 발생")

2. throw 키워드를 이용해서 예외를 발생시킨다.
		
        throw e;
public class Main {

	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("프로그램종료");
	}
}

 

#throws 키워드

 

try-catch 문을 이용하는 거 외에 예외를 메소드에 선언하는 방법이 있다.

메소드의 선언부에 throws 키워드를 사용해서 메소드 내에서 발생할 수 있는 예외를 적어주면 된다.

예외가 여러개면 , (쉼표)로 구분해준다.

void method() throws Exception1, Exception2, ... ExceptionN{
	//메소드 내용
}
public class Main {

	public static void main(String[] args) throws Exception {
		method1(); // 같은 클래스내 static 멤버 이므로 객체생성 없이 호출가능.
	}
	static void method1() throws Exception{
		method2();
	}
	static void method2() throws Exception{
		throw new Exception();
	}
}

throws로 예외를 선언하면 자식 타입의 예외까지도 발생할 수 있다는 점에 조심해야 한다.

오버 라이딩할 때는 단순히 선언된 예외의 개수가 아니라 상속관계까지 고려해줘야 한다.

 

예를 들어서 IllegalMonitorStateException 은 RuntimeException 클래스의 자식이기 때문에 IllegalMonitorStateException은 예외 처리를 해주지 않아도 된다. 

Java API 문서를 보고 메소드의 선언부와 Thorws 부분을 보고 메소드 끼리 연관 지어서 확인해주는 것이 좋다.

 

#finally 키워드

 

finally 키워드 블럭은 예외의 발생 여부와 상관없이 실행되어야 하는 코드를 포함시키는 역할을 한다.

try-catch문의 끝에 선택적으로 덧붙여 사용할 수 있으며 try-catch-finally의 순서로 구성된다.

try {
	//예외 발생가능성 문장
}catch (Exception1 e1) {
	//예외발생시 예외처리 문장
}finally {
	//항상 수행되어야 하는 문장
}

 

 

#자바가 제공하는 예외 계층 구조

 

자바에서는 실행 시 발생할 수 있는 오류(Exception 과 Error)를 클래스로 정리하였다.

모든 클래스의 조상은 Object이고 Exception과 Error 클래스 역시 Object클래스의 자식들이다.

 

출처:자바의 정석

#RuntimeException과 RE가 아닌 것의 차이는?

 

  • RE클래스 들은 주로 개발자 실수에 의해서 발생될 수 있는 예외들로 자바의 프로그래밍 요소들과 관계가 있다. 예를 들어 배열의 범위를 벗어나거나, 값이 null인 참조 변수의 멤버를 호출하거나, 클래스 간의 형 변환을 잘못하거나 하는 경우에 발생한다.
  • RE가 아닌 예외의 클래스들에서는 외부의 영향으로 발생할 수 있는 것들로서, 프로그램을 사용하는 사용자들의 동작에 의해서 발생하는 경우가 많다. 실수로 클래스의 이름을 잘못 적거나, 입력한 데이터 형식이 잘못되거나 하는 경우에 발생한다.

 

#에러와 예외 (Error와 Exception의 차이점)

 

프로그램이 실행 중에 어떤 원인에 의해서 오작동을 하거나 비정상적으로 종료되는 경우가 있는데 이럴 때 원인을 에러, 또는 오류라고 한다.

에러는 발생 시점에 따라 컴파일 에러, 런타임 에러, 논리적 에러로 나눌 수 있다.

컴파일 에러는 컴파일 시에 발생하는 에러, 런타임에러 실행 시에 발생하는 에러이고, 논리적 에러는 실행은 되는데 의도와 다른 게 동작하는 에러이다.

 

'에러' 는 일단 발생하면 복구할 수 없는 심각한 오류이고

'예외' 는 발생하더라도 수습될 수 있는 상대적으로 덜 심각하다.

예외처리의 정의는 프로그램 실행 시 발생할 수 있는 예외에 대비한 코드를 작성하는 것이고,

예외처리의 목적은 프로그램의 비정상적인 종료를 막고 정상적인 실행상태를 유지하는 것이다.

 

 

#커스텀한 예외 만드는 방법

 

보통은 Exception 클래스나 RuntimeException클래스로 부터 상속받아 클래스를 만들지만, 커스텀해서 만들 수 있다.

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

요즘은 예외처리를 선택적으로 할 수 있도록 Exception이 아닌 RE 를 상속받아서 작성하는 쪽으로 바뀌어가고 있다.

public class Main {

	public static void main(String[] args) {
		try {
			startInstall();
			copyFiles();
		}catch(SpaceException e) {
			System.out.println("에러 :"+ e.getMessage());
			e.PrintStackTrace();
			System.out.println("공간확보후 다시설치");
		}
	
	}
}
class SpaceException extends Exception{
	SpaceException(String msg){
		super(msg);
	}
}

 

반응형