티스토리 뷰

주의 사항!

  • 이 글은 제가 직접 공부하는 중에 작성되고 있습니다.
  • 따라서 제가 이해하는 그대로의 내용이 포함됩니다.
  • 따라서 이 글은 사실과는 다른 내용이 포함될 수 있습니다.


자바에서는 에러 이외에 예외(exception)라고 부르는 오류가 있습니다. 예외란, 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인해 발생하는 프로그램 오류를 말합니다. 예외가 발생되면 프로그램은 곧바로 종료된다는 점에서는 에러와 동일합니다. 그러나 예외는 예외 처리(Exception Handling)를 통해 프로그램을 종료하지 않고 정상 실행 상태가 유지되도록 할 수 있습니다.

 

예외는 두 가지 종류가 있습니다. 하나는 일반 예외(Exception)이고, 다른 하나는 실행 예외(RuntimeException)입니다. 일반 예외는 컴파일러 체크 예외라고도 하는데, 자바 소스를 컴파일하는 과정에서 예외 처리 코드가 필요한지 검사하기 때문입니다. 만약 예외 처리 코드가 없다면 컴파일 오류가 발생합니다. 실행 예외는 컴파일하는 과정에서 예외 처리 코드를 검사하지 않는 예외를 말합니다. 컴파일 시 예외 처리를 확인하는 차이일 뿐, 두 가지 예외는 모두 예외 처리가 필요합니다. 

 

자바에서는 예외를 클래스로 관리합니다. JVM은 프로그램을 실행하는 도중에 예외가 발생하면 해당 예외 클래스로 객체를 생성합니다. 그러고 나서 예외 처리 코드에서 예외가 발생하면 해당 예외 클래스로 객체를 생성합니다. 그러고 나서 예외 처리 코드에서 예외 객체를 이용할 수 있도록 해줍니다. 모든 예외 클래스들은 java.lang.Exception 클래스를 상속받습니다.

 

일반 예외와 실행 예외 클래스를 구별하는 방법은 일반 예외는 Exception을 상속받지만 RuntimeException을 상속받지 않는 클래스들이고, 실행 예외는 RuntimeException을 상속받은 클래스들입니다. RuntimeException 역시 Exception을 상속받지만, JVM은 RuntimeException을 상속했는지 여부를 보고 실행 예외를 판단합니다.

 

1. 실행 예외

실행 예외는 자바 컴파일러가 체크를 하지 않기 때문에 오로지 개발자의 경험에 의해서 예외 처리 코드를 삽입해야 합니다. 만약 개발자가 실행 예외에 대해 예외 처리 코드를 넣지 않았을 경우, 해당 예외가 발생하면 프로그램은 곧바로 종료됩니다. 자바 프로그램 개발 경력이 풍부하다면 언제, 어떤 실행 예외가 발생하는지 쉽게 알 수 있지만, 이제 시작하는 개발자라면 지금부터 설명하는 몇 가지 실행 예외를 잘 익혀두는 것을 권합니다. 자바 프로그램에서 자주 발생되는 실행 예외이므로 언제 발생되고, 어떤 오류 메시지가 출력되는지 잘 알아둘 필요가 있습니다.

 

1. 1. NullPointerException

자바 프로그램에서 가장 빈번하게 발생하는 실행 예외는 java.lang.NullPointerException일 것입니다. 이것은 객체 참조가 없는 상태, 즉 null값을 갖는 참조 변수로 객체 접근 연산자인 도트(.)를 사용할 때 발생합니다.

//exam00.java
package chapter00.exam00;

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

/*
실행결과

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.toString()" because "data" is null
	at chapter00/chapter00.exam00.exam00.main(exam00.java:9)

*/

위 코드는 참조 변수인 data에 일부러 null을 주고 이에 객체 접근 연산자 도트(.)를 사용했습니다. 위 코드를 작성하기까지는 컴파일러는 오류를 잡아내지 못합니다. 하지만 실행해보면 실행 예외가 발생합니다.

 

1. 2. ArrayIndexOutOfBoundsException

배열에서 인덱스 범위를 초과하여 사용할 경우 실행 예외인 java.lang.ArrayIndexOutOfBoundsException이 발생합니다. 예를 들어 길이가 3인 int[] arr = new int[3] 배열을 선언했다면, 배열 항목을 지정하기 위해 인덱스는 0 ~ 2를 사용할 수 있습니다. 하지만 이 범위를 벗어나는 인덱스를 사용하면 해당 예외가 발생합니다.

//exam00.java
package chapter00.exam00;

public class exam00 
{
	public static void main(String[] args)
	{
		int[] arr = new int[3];
		arr[3] = 2;
	}
}

/*
실행결과

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
	at chapter00/chapter00.exam00.exam00.main(exam00.java:9)

*/

이 역시 코드 작성할 때는 컴파일러가 오류를 잡아내지 못하지만 실행해보면 실행 예외가 발생합니다.

 

1. 3. NumberFormatException

프로그램을 개발하다 보면 문자열로 되어 있는 데이터를 숫자로 변경하는 경우가 자주 발생합니다. 문자열을 숫자로 변환하는 방법은 여러 가지가 있지만 가장 많이 사용되는 코드는 다음과 같습니다.

String str = "2021";
int var1 = Integer.parseInt(str);
double var2 = Double.parseDouble(str);

Integer와 Double은 포장(Wrapper) 클래스라고 하는데, 이는 나중에 자세히 설명합니다. 이 클래스의 정적 메서드인 parseXXX() 메서드를 이용하면 문자열을 숫자로 변환할 수 있습니다. 이 메서드들은 매개 값인 문자열이 숫자로 변환될 수 있다면 숫자를 리턴 하지만, 숫자로 변환될 수 없는 문자가 포함되어 있다면 java.lang.NumberFormatException을 발생시킵니다.

//exam00.java
package chapter00.exam00;

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

/*
실행결과

Exception in thread "main" java.lang.NumberFormatException: For input string: "a100"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
	at java.base/java.lang.Integer.parseInt(Integer.java:652)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at chapter00/chapter00.exam00.exam00.main(exam00.java:12)

*/

 

1. 4. ClassCastException

타입 변환(Casting)은 상위 클래스와 하위 클래스 간에 발생하고 구현 클래스와 인터페이스 간에도 발생합니다. 이러한 관계가 아니라면 클래스는 다른 클래스로 타입 변환할 수 없습니다. 억지로 타입 변환을 시도할 경우 ClassCastException이 발생합니다.

 

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

//exam00.java
package chapter00.exam00;

public class exam00 
{
	public static void main(String[] args)
	{
		class Animal {}
		class Dog extends Animal {}
		class Cat extends Animal {}
		
		Animal animal = new Dog();
		Cat cat = (Cat)animal;
	}
}

/*
실행결과

Exception in thread "main" java.lang.ClassCastException: class chapter00.exam00.exam00$1Dog cannot be cast to class chapter00.exam00.exam00$1Cat (chapter00.exam00.exam00$1Dog and chapter00.exam00.exam00$1Cat are in module chapter00 of loader 'app')
	at chapter00/chapter00.exam00.exam00.main(exam00.java:13)

*/

 

'공부 일지 > JAVA 공부 일지' 카테고리의 다른 글

자바, 자동 리소스 닫기  (0) 2021.04.13
자바, 예외 처리 코드  (0) 2021.04.13
자바, 익명 객체  (0) 2021.04.13
자바, 중첩 인터페이스  (0) 2021.04.13
자바, 중첩 클래스의 접근 제한  (0) 2021.04.11
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함