[자바] 예외 처리

이정우·2021년 8월 13일
0

자바

목록 보기
7/9

JVM에서 자바 코드 실행 중 문제가 있다면 콘솔 창에 에러가 뜨는것을 볼 수 있습니다. 에러의 경우에는 개발자가 대처할 방법이 거의 존재하지 않습니다. 또한 자바에서는 에러외에 예외라는게 존재합니다. 예외는 사용자 혹은 개발자가 프로그램을 잘못 조작하거나 코딩을 잘못해서 발생하게 됩니다. 예외 상황이 발생하면 프로그램은 예외 발생 지점에서 프로그램을 종료하게 됩니다. 하지만 예외 처리를 통해 예외가 발생해도 계속 프로그램을 실행시킬 수 있습니다. 또한 자바 JVM은 예외를 클래스로 만들어 관리하고 모든 예외는 java.lang.Exception클래스를 상속받습니다.

예외의 종류 1. 일반 예외(Exception)

예외에는 두가지 종류가 있습니다. 그 중 하나가 일반 예외로, 흔히 "컴파일러 체크 예외"라고 불립니다. 일반 예외는 소스를 컴파일 하는 과정에서 예외 처리가 필요한지 검사하고 예외 처리 과정이 존재하지 않는다면 컴파일 오류를 발생시킵니다. 또한 일반 예외는 RuntimeException을 제외한 모든 예외 클래스를 상속받는 예외입니다. 또한 예외 발생시 반드시 try-catch등으로 처리를 해줘야합니다. 이클립스의 경우에는 컴파일 과정에서 예외를 확인하고 빨간 선으로 사용자에게 보여주고 시스템이 추천하는 예외 처리 방법 또한 제시해 줍니다.

예외의 종류 2. 실행 예외(RuntimeException)

실행 예외는 일반 예외와 다르게 컴파일 과정에서 예외 처리 코드를 검사하지 않는 예외입니다. 또한 일반 예외와는 다르게 실행 예외만이 RuntimeException 예외 클래스를 상속받습니다. 실행 예외는 자바 컴파일러가 체크를 해주지 않기에(이클립스에서 빨간 선으로 에러 표시를 해주지 않음) 개발자가 자신의 역량으로 찾고 예외 처리를 해주어야 합니다. 또한 실행 예외는 일반 예외와는 다르게 반드시 예외 처리를 강제하지는 않습니다.

실행 예외의 종류

많이 발생하는 실행 예외로는
- 객체 참조가 없는 상태(null)에서 객체 접근 연산자(.도트)를 사용하는 경우에 발생하는 NullPointerException
- 능동적으로 크기를 늘리고 줄일 수 없는 배열에 대해 범위 오류가 발생할 경우 나오는 ArrayIndexOutOfBoundsException
- 문자열을 숫자로 바꿀 때 바꿀 수 없는 문자가 들어있을 경우 흔히 나오는 NumberFormatException
- 알맞지 않은 클래스간의 타입 변환시 발생하는 ClassCastException등이 있습니다.

이러한 실행 예외는 if문을 사용해서 예외를 확인해 주거나 예외가 발생한 부분의 코드를 수정해 주거나 예외 처리를 해주어야 합니다.

예외 처리

예외를 처리하는 이유는 프로그램의 갑작스러운 종료를 막기 위함입니다. 예외 처리 코드에는 try - catch - finally가 있습니다.

try{
 예외가 발생할 가능성이 있는 코드
}catch(예외 클래스 e) {
 알맞는 예외 처리
}finally {
 무슨일이 발생하여도 무조건 실행
}

try 블록에는 예외가 발생할 가능성이 있는 코드를 넣습니다. 여기서 만약 예외가 발생한다면
- catch의 예외 발생 지점에서 강제 종료 후 -> finally 블록으로 갑니다.
- 예외가 발생하지 않았다면 try -> finally 순으로 실행이 됩니다. try, catch문에서 return을 사용해도 finally문을 스킵할 수는 없습니다. 또한 finally은 생략이 가능합니다.

try{
int a = Integer.parseInt("123A");
int b = Integer.parseInt("123");
}catch(NumberFormatException e) {
System.out.print("숫자로 변환할 수 없습니다. 문자가 포함되어 있는지 확인하여 주십시오.);
}finally {
System.out.pirntln("프로그램 마지막 부분");
}

우선 int a의 값인 "123A"를 보면 A는 숫자로 바꿀 수 없는 문자입니다. 그렇기에 NumberFormatException이 발생하게 되고 밑의 int b부분을 실행하지 않고 스킵한 다음 바로 catch문으로 가서 print문을 실행하고 마지막으로 finally를 실행합니다.

다중 catch 멀티 catch, catch의 순서

try {
ArrayIndexOutOfBoundsException 발생

NumberFormatException 발생

NullPointerException 발생

}catch(Exception e){
 예외 처리
}catch(ArrayIndexOutOfBoundsException e){
 예외 처리
 }catch(NumberFormatException | NullPointerException) {
 예외 처리 
 }

위 코드를 보기전에 catch문은 다중으로 여러개 생성이 가능하며 실행 순서는 맨 위에부터 순차적으로 실행해서 확인해 나갑니다.
예를 들어 NullPointerException 발생했다면 catch(Exception e) => catch(ArrayIndexOutOfBoundsException e) =>catch(NumberFormatException | NullPointerException) 순서로 오류가 각 catch문에 맞는지 확인합니다.
여기서 오류는 클래스로 관리가 되고 최상위 클래스는 Exception입니다. 즉, 만약 위의 경우에서 ArrayIndexOutOfBoundsException가 발생하였다면 실행되는 catch문은 맨 처음 있는 catch(Exception e)입니다. 최상위 클래스 때문에 밑의 catch문에 도달하지 못한 경우인 것입니다. 그렇기에 이러한 경우를 방지하기 위해 하위 클래스일수록 위에 적어주는것이 좋습니다. 물론 이러한 방법의 오류 처리 방식은 모든 오류를 Exception으로 처리해주면 편할 순 있지만 자세하게 어떠한 오류인지 알 수 없어 사후 처리에도 문제가 발생할 수 있는 나쁜 오류 처리 방법입니다. 또한 catch(NumberFormatException | NullPointerException) 처럼 멀티 catch문을 사용해서 한 줄에 여러 오류를 처리할 수도 있습니다.

예외 떠넘기기

	public static void cal() throws ArrayIndexOutOfBoundsException{
		int[] a = {1,2,3,4};
		System.out.println(a[4]);
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		try{
			cal();
		}catch(ArrayIndexOutOfBoundsException e){
			System.out.println("오류 발생!");
		}
	}

throws를 이용해 당장에 오류를 무시하고 떠넘길 수 있습니다. 유의할 점은 실행할 경우 try문 안에서 실행을 해야합니다.

사용자 정의 예외 클레스

public class BaException extends Exception{
	public BaException() {
	}
	public BaException(String message) {
		super(message);
	}
}


public class Batest {
	public static void main(String[] args) {
	try {
		throw new BaException();
	}catch(BaException e) {
		System.out.println("성공");
	}
	}
}

사용자가 임의의 예외문을 만들수도 있습니다. 예외문을 강제 실행할 때는 throw new xxException을 사용하면 됩니다.

예외 정보 얻기

최상위 클래스인 Exception의 getMessage() 메소드와 printStackTrace()메소드를 통해 예외 정보를 얻을 수 있습니다.

public class Batest {
	public static void main(String[] args) {
		try{
			int[] a = {1,2,3,4};
			System.out.println(a[5]);
		}catch(ArrayIndexOutOfBoundsException e){
			String message = e.getMessage();
			System.out.println(message);
			e.printStackTrace();
		}
	}
	}


실행 결과
Index 5 out of bounds for length 4
java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 4
	at test.Batest.main(Batest.java:7)

보면 getMessage를 통해 예외의 원인인 Index 5 out of bounds for length 4 이라는 예외 사실을 알 수 있고 printStackTrace()를 통해 Index 5 out of bounds for length 4이라는 예외 내용과 Batest.java의 7라인 이라는 예외 근원지를 알 수 있습니다.

정리

오늘 수업에서는 예외 처리 코드의 필요성과 방법 종류등을 배웠습니다. 아직 많은 예외 코드를 보지 못해 경험도 부족하고 대처 방법도 미약하지만 뭐든지 일단 아는게 힘이라고 기본적인 사용 방법들과 종류를 알았다는 점에서 수확이 있었다고 생각합니다. 그래도 역시 자주 써본게 아니라 쉽지는 않았습니다!

참고 자료 : 이것이 자바다 , 국비 교육 내용

profile
프로그래밍 공부 중!

0개의 댓글