본문 바로가기

Java/Java

예외 처리_예외 클래스

1. 예외

컴퓨터 하드웨어의 오동작 또는 고장으로 인해 발생하는 응용 프래그램의 실행 오류를 통상적으로 에러라 칭한다.

예외는 이러한 에러 이외에 프로그램 자체에서 발생하는 오류를 말한다.

 

예외를 다시 정의하자면, 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인해 발생하는 프로그램의 오류를 말한다.

발생할 경우 프로그램이 종료된다는 점에서 에러와 예외는 유사하지만, 예외의 경우 예외 처리를 통해 프로그램을 종료하지 않고 정상적으로 유지할 수 있다.

 

자바는 예외가 발생할 확률이 높은 코드를 컴파일 할때 자동적으로 예외 처리 유무를 확인한다.

확인 결과 예외 처리가 되어있지 않다면, 컴파일 되지 않는다.

하지만 모든 예외에 대해서 예외 처리 유무를 확인하는 것은 아니며, 예외의 종류에 따라 다르다.

 

 

2. 예외와 예외 클래스

예외는 일반 예외(exception)실행 예외(runtime exception)로 구분할 수 있다.

 

일반 예외는 컴파일러 체크 예외라고도 한다.

말그대로 프로그램 실행 시 예외 발생 가능성이 높기 때문에 컴파일 과정에서 예외 처리 유무를 확인한다. 

만약 예외 처리가 되어있지 않다면, 컴파일 오류가 발생한다.

 

실행 예외는 컴파일러 넌 체크 예외라고도 한다. 

말그대로 컴파일 과정에서 예외 처리 유무가 확인 되지 않는 예외인데, 그 이유는 프로그램 실행 시 예측할 수 없이 갑자기 발생하기 때문이다. 

 

자바에서는 예외를 클래스로 관리한다. JVM은 프로그램 실행 시 예외가 발상하면, 해당 예외 클래스의 객체를 생성한다. 그리고 예외 처리 코드에서 예외 객체를 이용할 수 있도록 해준다.

 

다양한 예외 클래스가 존재하며, 모든 예외 클래스는 java.lang.Exception클래스를 상속한다.

그리고 일반 예외와 실행 예외는 java.lang.RuntimeException클래스를 기준으로 구분한다.

java.lang.RuntimeException을 상속할 경우 실행 예외이며, 아닌 경우에는 일반 예외이다.

 

 

3. 실행 예외

앞서 말했듯이 실행 예외는 컴파일러가 자동으로 예외 처리 유무를 확인하지 않기 때문에 오로지 개발자의 경험에 의해서 예외 처리 코드를 작성해야한다.

만약 개발자가 실행 예외에 대해 예외 처리 코드를 작성하지 않았을 경우, 해당 예외가 발생하면 프로그램은 종료된다.

 

1) NullPointException

java.lang.NullPointException은 가장 빈번히 발생하는 실행 예외 중 하나이다.

이 실행 예외는 객체를 참조하지 않고 있는 상태(null)의 참조 변수로 객체 접근 연산자인 .를 사용했을 때 발생한다. 

 

아래의 예제 코드는 NullPointException예외의 예를 보여준다.

data변수는 현재 객체를 참조하고 있지 않다.

그러한 상황에서 . 연산자를 통해 객체에 접근하려고 시도하기 때문에 NullPointException예외가 발생한다.

package sec01.exam01;

public class NullPointerExceptionExample {

	public static void main(String[] args) {
		String data = null;
		System.out.println(data.toString());

	}

}

 

2) ArrayIndexOutOfBoundsException

배열의 인덱스 범위를 초과해서 사용할 경우 java.lang.ArrayIndexOutOfBoundsException실행 예외가 발생한다.

 

아래의 예제코드는 ArrayIndexOutOfBoundsException예외의 예를 보여준다.

String data1 = args[0];에서 예외가 발생한다.

그 이유는 args변수에 0, 1 인덱스 값이 없기 때문이다.

package sec01.exam02;

public class ArrayIndexOutOfBoundsExceptionExample {

	public static void main(String[] args) {
		String data1 = args[0];
		String data2 = args[1];
		
		System.out.println("arg[0]: " + data1);
		System.out.println("arg[1]: " + data2);

	}

}

 

아래의 예제 코드는 ArrayIndexOutOfBoundsException예외의 처리에 대한 좋은 예이다.

배열 값을 사용하기 전에 배열의 길이를 먼저 조사하여, 예외 발생 시 프로그램 종료를 방지 하는 것이다.

package sec01.exam03;

public class ArrayIndexOutBoundsException {

	public static void main(String[] args) {
		if(args.length == 2) {
			String data1 = args[0];
			String data2 = args[1];
			System.out.println("args[0]: " + data1);
			System.out.println("args[1]: " + data2);
		} else {
			System.out.println("두 개의 실행 매개값이 필요합니다.");
		}

	}

}

 

3) NumberFormatException

java.lang.NumberFormatException실행 예외는 문자열 데이터를 숫자 데이터로 변환할 때 발생한다.

예를 들어 Integer.parseInt(String s) 또는 Double.parseDouble(String s)메소드를 통해 문자열을 정수 또는 실수로 변환할 수 있다. 

이 때 문자열이 정수 또는 실수로 변환될 수 있다면 정상적으로 숫자 데이터를 반환하지만, 숫자 데이터로 변환될 수 없는 문자열일 경우에는 NumberFormatException이 발생한다.

 

아래의 예제코드는 NumberFormatException의 예를 보여준다.

data2변수에는 숫자 데이터로 변환될 수 없는 "a100" 문자열이 저장되어 있다. 

그래서 int value2 = Integer.parseInt(data2)를 통해 숫자 데이터로 변환하려 시도할 때 NumberFormatException이 발생한다. 

package sec01.exam04;

public class NumberFormatException {

	public static void main(String[] args) {
		String data1 = "100";
		String data2 = "100a";
		
		int value1 = Integer.parseInt(data1);
		int value2 = Integer.parseInt(data2);
		
		int result = value1 + value2;
		System.out.println(data1 + "+" + data2 + "=" + result);

	}

}

 

4) ClassCastException

클래스의 타입 변환(Casting)은 상위 클래스와 하위 클래스, 인터페이스와 구현 클래스 간에 가능하다.

이러한 관계를 갖지 않은 클래스 타입으로는 변환할 수 없다.

이처럼 불가능한 상황에서 타입 변환을 시도할 경우 java.lang.ClassCastException이 발생한다. 

 

아래의 예제 코드는 ClassCastException예외의 예를 보여준다.

부모 클래스인 Animal, 자식 클래스인 Dog클래스와 Cat클래스가 존재한다.

ChangeDog메소드는 Animal타입 객체를 매개값으로 받아 Dog타입으로 변환하는 메소드이다.

 

예외 처리를 하지 않을 경우, 예제 코드에서는 changeDog(cat)에서 ClassCastException이 발생한다.

Dog타입으로 변환될 수 없는 Cat객체가 매개값으로 사용됐기 때문이다.

 

예외 처리를 위해서 주석 처리된 조건문의 주석을 해제하여 메소드 내용을 실행하기 전에 매개값이 Dog객체를 참조하고 있는지 확인해주는 것이 좋다.

package sec01.exam05;

public class ClassCastExceptionExample {

	public static void main(String[] args) {
		Dog dog = new Dog();
		changeDog(dog);
		
		Cat cat = new Cat();
		changeDog(cat);
	}
	
	public static void changeDog(Animal animal) {
		//if(animal instanceof Dog) {
		Dog dog = (Dog) animal;
		//}
	}
}

class Animal{}
class Dog extends Animal {}
class Cat extends Animal {}

 

출처: 혼자 공부하는 자바(신용권)