본문 바로가기
Java & Spring

java) 예외 처리

by softserve 2021. 12. 13.
반응형

1. 예외란 무엇인가

 

 

Error와 Exception은 Throwable의 서브클래스입니다.

Error는 시스템상의 중대한 오류이며

Exception은 프로그래머가 의도하지 않았던 돌발적인 상황, 즉 예외를 말합니다.

Exception은 다시 RuntimeException과 그 밖의 예외로 나눌 수 있습니다.

RuntimeException은 실행시 발생하는 예외로, 컴파일러가 확인하지 않는 unchecked exception 입니다.

RuntimeException이 아닌 예외들은 모두 checked exception 입니다. 컴파일러가 처리 여부를 확인하므로 코드에서 반드시 처리되어야 합니다.

java에서는 예외도 객체로 취급하므로 예외를 만들고 주고받으면서 노는 것이 가능합니다.

 

2. 예외를 처리하는 방법

 

예외에 대처하는 가장 좋은 방법은 발생할 수 있는 모든 상황을 미리 예측하고 그 각각에 대해 대응하는 것입니다.

예를 들어, 숫자 두 개를 입력받아 나눗셈을 하는 프로그램에서 사용자가 분모 값으로 0을 입력한다면

그러지 말라고 친절하게 알려준 뒤, 다시 입력을 받는 방식으로 해결할 수 있습니다.

직접 처리할 수 있는 것은 직접 처리함으로써 조금 더 효율을 높일 수 있습니다.

 

그리고 미처 처리하지 못한 나머지 예외들은 try ~ catch를 통해 잡아낼 수 있습니다.

public static void main(String[] args) {
		double  result;
		Scanner s = new Scanner(System.in);
		
		try {
			int op1 = s.nextInt(), op2 = s.nextInt();
			result = divide(op1,op2);
			System.out.println(op1+"/"+op2+"="+result); // 예외발생시 실행되지 않음
		}
		catch ( ArithmeticException e) {
			System.out.println(e.getMessage());
		}
		finally {
			close(); // 예외발생시에도 실행됨
		}
}
public static void close() {
	System.out.println("System terminated");
}

1) try 문에는 예외 발생 여부를 감시할 문장이 들어갑니다.

2) catch 문에는 예외 발생 시 조치를 넣습니다. 예외의 범위를 클래스 이름으로 지정할 수 있습니다.

- Exception은 모든 예외를 잡아냅니다.

- RuntimeException은 RuntimeException만을 잡아냅니다.

- 예제의 ArithmeticException은 0으로 나누는 것만 잡아냅니다.

- 한편, 복수의 예외를 처리할 수도 있습니다. 이때 구체적인 것을 먼저 잡아야 합니다.

try {
 // do something
} 
catch(SpecificException e1) {
}
catch(Exception e2) {
}

만약 Exception과 SpecificException의 순서가 바뀌면 첫 번째 catch문에서 모든 예외를 잡아버리므로 두 번째 catch문은 실행되지 않습니다.

- e.toString() e.getMessage() e.printStackTrace() 의 결과는 순서대로

입니다.

3) finally 에는 예외 발생 여부에 관계없이 반드시 실행되어야 하는 문장을 넣습니다.

- 위 예제는 사용자로부터 입력받은 값 op1과 op2를 나눈 결과를 result에 저장한 뒤 출력합니다.

- 만약 나누기( divide)를 수행하는 과정에서 0으로 나누는 등 예외가 발생하면 마지막 출력문을 실행하지 않고 catch문으로 넘어가게 됩니다.

- 따라서 close 등 반드시 수행되어야 하는 부분은 try 문에 들어가지 않도록 해야 하고, 이를 확실히 하기 위해서 finally 블록에 넣어둡니다.

 

3. 예외의 정의 및 생성, 던지기

 

Exception 클래스를 상속받아 새로운 예외를 정의할 수 있습니다.

class DBZException extends ArithmeticException {
	public DBZException() {
		super("can not divide by zero");
	}
}

예외를 발생시키기 위해  throw  키워드로 새로운 예외 객체를 생성합니다.

메서드 내부에서 예외 처리를 할 수도 있지만,

 throws  로 예외 발생 시 상위 메서드로 전달(미루기) 할 수 있습니다.

한편, checked exception을 발생시킬 수 있는 메서드에는 throws로 그 예외들을 나열해주어야 합니다.

ex) 입출력시 main 메서드에 throws IOException 을 적지 않으면 컴파일 에러가 발생

복수도 가능 main(String[] args) throws IOException, IOIException, IOIOException { ... }

public static double divide(int num1, int num2) throws DBZException { // 상위 메서드로 던짐
	if(num2==0) throw new DBZException(); // 예외객체를 생성
	return (double) num1/num2;
}

 

* 예외의 종류, Exception의 서브클래스

https://docs.oracle.com/javase/7/docs/api/java/lang/Exception.html

반응형

댓글