[Java] 예외 처리

kiteB·2022년 1월 26일
0

Java

목록 보기
25/35
post-thumbnail

[ 예외와 예외 처리 ]

1. 오류와 예외

  • 오류(error)란 컴퓨터 하드웨어의 오동작 또는 고장으로 인해 응용프로그램 실행 오류가 발생하는 것을 의미한다.
  • 예외(exception)란 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인해 발생하는 프로그램 오류를 말한다.

오류는 JVM 실행에 문제가 생겼다는 뜻이므로 개발자가 이러한 오류에 대처할 방법이 없다.
예외가 발생되면 프로그램이 곧바로 종료된다는 점에서는 오류와 동일하지만 예외 처리(Exception Hangling)를 통해 프로그램을 종료하지 않고 정상 실행 상태가 유지되도록 할 수 있다.


2. 예외

예외는 크게 일반 예외(Exception)와 실행 예외(Runtime Exception)로 나뉜다.

일반 예외는 자바 소스를 컴파일하는 과정에서 예외 처리 코드가 필요한지 검사하기 때문에 컴파일러 체크 예외라고도 한다.
실행 예외는 컴파일하는 과정에서 예외 처리 코드를 검사하지 않는 예외를 말한다. 두 예외 모두 예외 처리가 필요하다!

자바는 예외를 클래스로 관리한다.

JVM은 프로그램을 실행하는 도중에 예외가 발생하면 해당 예외 클래스로 객체를 생성한 뒤, 예외 처리 코드에서 예외 객체를 이용할 수 있도록 한다. 모든 예외 클래스는 java.lang.Exception 클래스를 상속받는다.

📌 일반 예외와 실행 예외를 구별하는 방법

일반 예외는 Exception을 상속받지만, RuntimeException을 상속받지 않는 클래스들이고, 실행 예외는RuntimeException을 상속받는 클래스들이다.

RuntimeException 역시 Exception을 상속받지만, JVM은 RuntimeException을 상속했는지 여부를 보고 실행 예외를 판단한다.


[ 실행 예외 ]

실행 예외는 자바 컴파일러가 체크하지 않기 때문에 오로지 개발자의 경험에 의해서 예외 처리 코드를 삽입해야 한다. 만약 개발자가 실행 예외에 대해 예외 처리 코드를 넣지 않았을 경우, 해당 예외가 발생하면 프로그램이 곧바로 종료된다. 이러한 일을 방지하기 위해서는 지금부터 자바 프로그램에서 자주 실행되는 실행 예외에 대해 알아두어야 한다!

1. NullPointerException

객체 참조가 없는 상태, 즉 null 값을 갖는 참조 변수로 객체 접근 연산자인 .를 사용했을 때 발생한다.

객체가 없는 상태에서 객체를 사용하려고 해서 예외가 발생하는 것이다.

예제

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

datanull 값을 가지고 있기 때문에 String 객체를 참조하고 있지 않은데, 이 String 객체의 toString() 메소드를 호출하고 있기 때문에 NullPointerException이 발생한다.


2. ArrayIndexOutOfBoundsException

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

예를 들어 길이가 3인 int[] arr = new int[3] 배열을 선언했다면,

  • 배열 항목을 저장하기 위해 arr[0] ~ arr[2]를 사용할 수 있다.
  • 하지만 arr[3]를 사용하면 인덱스 범위를 초과했기 때문에 ArrayIndexOutOfBoundsException이 발생한다.

예제

public class ArrayOutOfBoundsExceptionExample {
    public static void main(String[] args) {
        String data1 = args[0];
        String data2 = args[1];

        System.out.println("args[0]: " + data1);
        System.out.println("args[1]: " + data2);
    }
}

위의 코드를 실행하면 String data1 = args[0]; 에서 ArrayIndexOutOfBoundsException가 발생한다.
두 개의 실행 매개값을 주지 않았기 때문에 args[0], args[1]을 사용할 수 없기 때문이다!

예외가 발생하지 않도록 하려면 다음과 같이 수정하면 된다.

public class ArrayOutOfBoundsExceptionExample {
    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("[실행 방법]");
            System.out.println("java ArrayIndexOutOfBoundsExceptionExample ");
            System.out.println("값1 값2");
        }
    }
}

3. NumberFormatException

문자열로 되어 있는 데이터를 숫자로 변경할 때 다양한 방법이 있지만, 가장 많이 사용되는 코드는 다음과 같다.

IntegerDouble은 포장(Wrapper) 클래스라고도 하는데, 이 클래스의 정적 메소드인 parseXXX() 메소드를 이용하면 문자열을 숫자로 변환할 수 있다. 이 메소드들은 매개값이 문자열이 숫자로 변환될 수 있다면 숫자를 리턴하지만, 숫자로 변환할 수 없는 문자가 포함되어 있다면 java.lang.NumberFormatException을 발생시킨다.

public class NumberFormatExceptionExample {
    public static void main(String[] args) {
        String data1 = "100";
        String data2 = "a100";

        int value1 = Integer.parseInt(data1);
        int value2 = Integer.parseInt(data2);   //NumberFormatException 발생

        int result = value1 + value2;
        System.out.println(data1 + "+" + data2 + "=" + result);
    }
}

4. ClassCastException

억지로 타입 변환을 시도할 경우 ClassCastException이 발생한다.

ClassCastException을 발생시키지 않으려면 타입 변환 전에 타입 변환이 가능한지 instanceof 연산자로 확인하는 것이 좋다. instanceof의 연산의 결과가 true이면 좌항 객체를 우항 타입으로 변환이 가능하다는 뜻이다.

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) {
        Dog dog = (Dog) animal; //ClassCastException 발생 가능
    }
}
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

위의 코드를 실행해보면 changeDog(cat); 코드에서 Cat 객체를 매개값으로 주었기 때문에 Dog 타입으로 변환할 수 없어서 ClassCastException이 발생한다.

이렇게 잘못된 매개값이 들어올 수 있기 때문에 changeDog() 메소드를 다음과 같이 바꾸는 것이 좋다.

public static void changeDog(Animal animal) {
    if(animal instanceof Dog) {
        Dog dog = (Dog) animal; //ClassCastException 발생 가능
    }
}
profile
🚧 https://coji.tistory.com/ 🏠

0개의 댓글