예외 처리란
프로그램에서 예외가 발생했을 경우 프로그램은 갑작스럽게 종료를 하게 된다. 이를 막고 정상 실행을 유지할 수 있도록 도와주는 것이 예외 처리이다.
자바 컴파일러는 소스 파일을 컴파일할 때 일반 예외가 발생할 가능성이 있는 코드를 발견하면 컴파일 에러를 발생시켜 개발자가 강제적으로 예외 처리 코드를 작성하도록 요구한다.
(특정 에러들에 빨간 줄이 그여 실행이 안되도록 막아주는 친구들이다.)
그러나 실행 예외는 컴파일러가 체크하지 못하기 때문에 개발자의 경험을 바탕으로 예외 처리 코드를 작성해주어야 한다.
try-catch-finally 블록
try-catch-finally 블록이란 실행 예외가 발생할 경우 예외 처리를 할 수 있도록 해주는 블록이다.
- try 블록에는 예외가 발생할 가능성이 있는 코드가 위치한다.
- catch 블록에는 예외 처리 코드가 위치하고 있다.
try에서 예외가 발생할 시 즉시 실행을 멈추고 catch 블록 내부의 예외 처리 코드가 실행된다. - finally 블록은 try 블록 내부 코드의 예외 발생 여부와 관계없이 무조건 실행된다.
- finally 블록은 생략이 가능하다. 심지어 tryu 블록과 catch 블록에서 return문을 사용하더라도 finally 블록은 항상 실행된다.
public class ExampleCode {
public static void main(String[] args) {
try {
//ClassNotFound 발생 -> try로 이동
Class clazz = Class.forName("java.lang.String2");
} catch (ClassNotFoundException e) {
System.out.println("클래스가 존재하지 않습니다.");
}
}
}
자주 발생하는 실행 예외의 대표적 케이스
- NullPointerException(NPE)
매우 자주 나타나는 에러이다. NullPointException이라고 부르기 힘들어서 NPE라고 줄여 부르기도 한다.
이 에러는 객체 참고가 없는 상태, 즉 null 값을 가지고 있는 참조 변수로 객체 접근 연산자인 도트(.)를 사용했을 때 발생한다. - ArrayIndexOoutOfBoundsExeption
배열을 다룰때 주로 발생하는 예외.
배열에서 할당된 배열의 인덱스 범위를 초과해서 사용할 경우 발생한다. - NumberFormatException
프로그램을 개발하다 보면 문자열로 되어있는 데이터를 숫자로 변경하는 경우가 발생하곤 한다.
변환 타입 | 메소드명(매개변수) | 설명 |
int | Integer.parseInt(String s) | 주어진 문자열을 정수로 변환해서 리턴 |
Double | Double.parseDouble(String s) | 주어진 문자열을 실수로 변환해서 리턴 |
- 외에도 Float.parseFloat(String s) 등과 같이 문자열을 특정 수로 변경할 수 있다.
Integer와 Double은 포장(Wapper) 클래스라고 하는데
여기서 Wrapper 클래스란 본 자료타입(primitive type)을 객체로 다루기 위해 사용하는 클래스들을 래퍼 클래스(wrapper class) 하고한다.
만약 parseXXX() 메소드들을 이용하여 문자열을 숫자로 변환할 수 있지만 매개변수로 오는 문자열이 숫자로 변환이 되는 값이면 숫자를 리턴 하지만, 숫자로 변환될 수 없는 문자가 온다면 java.lang.NumberFormatException을 발생시킨다.
- ClassCastException
타입 변환(Casting)은 상위 클래스와 하위 클래스 간에 발생하고 구현 클래스와 인터페이스 간에도 발생한다.
이러한 관계가 아니라면 클래스는 다른 클래스를 타입으로 변환할 수 없다.
억지로 타입변환을 시도할 경우 ClassCastException이 발생한다.
다중 catch란
위에서 나온 대표적인 예외 이외에도 많은 예외가 있고 try 블록 내부는 다양한 예외가 발생할 수 있다.
이 경우 발생되는 예외 별로 예외 처리 코드를 다 작성하기 위해 다중 catch 블록이 활용된다.
catch 블록의 예외 클래스 타입은 try 블록에서 발생된 예외의 종류를 말하는데, try 블록에서 해당 타입의 예외가 발생한다면 catch 블록을 실행하도록 되어있다.
try 블록에서 동시 다발적으로 예외가 발생하지 않고, 하나의 예외가 발생하면 즉시 실행을 멈추고 해당 catch 블록으로 이동하기 때문에 catch 블록이 여러 개라 할지라도 단 하나의 catch 블록만 실행된다.
다중 catch문의 순서
다중 catch 블록을 작성할 때 주의해야 할 점은 상위 예외 클래스가 하위 예외 클래스보다 아래쪽에 위치해야 한다는 점이다.
(Exception은 모든 예외 클래스의 최상위 클래스이기에 다른 예외 클래스보다 위에 위치하면 안 된다.)
잘못된 코딩 예:
ArrayIndexOutOfBoundsException과 CumberFormatException은 모두 Exception을 상속받기 때문에 첫 번째 catch 블록만 선택되어 실행된다.
올바른 코딩 예:
try 블록에서 ArrayIndexOutOfBoundsException이 발행하면 첫 번째 catch 블록을 실행하고, 그 밖의 다른 예외가 발생하면 두 번째 catch 블록을 실행한다.
//올바른 코드 예시
public class ExampleCode {
public static void main(String[] args) {
try {
String data1 = args[0];
String data2 = args[1];
int value1 = Integer.parseInt(data1);
int value2 = Integer.parseInt(data2);
int result = value1 + value2;
System.out.println(data1 + "+" + data2 + "=" + result);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("실행 매개값의 수가 부족합니다.");
} catch (Exception e) {
System.out.println("실행에 문제가 있습니다.");
} finally {
System.out.println("다시 실행하세요.");
}
}
}
예외 떠넘기기
메서드 내부에서 예외가 발생할 수 있는 코드를 작성할 때 try-catch 블록으로 예외를 처리하는 것이 기본이지만
경우에 따라서는 메서드를 호출한 곳으로 예외를 떠넘길 수도 있다.
throw 키워드는 메소드 선언부 끝에 작성되어 메서드에서 처리하지 않은 예외를 호출한 곳으로 떠넘기는 역할을 한다.
리턴타입 메소드이름(매개변수,...) throws 예외클래스1, 예외클래스2, ...{
}
위와 같이 throws 키워드 뒤에는 떠넘길 예외 클래스를 쉼표로 구분해서 나열해주면 된다.
발생할 수 있는 예외의 종류별로 throws 뒤에 나열하는 것이 일반적이지만, 다음과 같이 throws Exception만으로 모든 예외를 간단히 떠넘길 수도 있다.
리턴타입 메소드이름(매개변수, ...) throw Exception{
}
throws 키워드가 붙어 있는 메서드는 반드시 tryu 블록 내에서 호출되어야 하고, catch 블록에서 떠넘겨 받은 예외처리를 해야 한다.
method1()에서도 try-catch 블록으로 예외를 처리하지 않고 다음과 같이 throws 키워드로 다시 예외를 떠넘길 수 있다.
그러면 method1()을 호출하는 곳에서 try-catch 블록을 사용해서 예외를 처리해야 한다.
public void method1() throws ClassNotFoundException{
method2();
}
//example code
public class ThrowsExample {
public static void main(String[] args) {
try {
findClass();
}catch(ClassNotFoundException e){
System.out.println("클래스가 존재하지 않습니다.");
}
}
public static void findClass() throws ClassNotFoundException{
Class clazz=Class.forName("java.lang.String2");
}
}
'📖혼자공부하는자바' 카테고리의 다른 글
Http 상태코드 (0) | 2023.07.19 |
---|---|
Chapter13-2 LIFO와 FIFO 컬렉션 (0) | 2022.12.24 |
Chapter 07-3 추상 클래스, 추상 메소드 (0) | 2022.12.10 |
Chapter 06-6-1 패키지와 접근 제한자 (0) | 2022.12.02 |
Chapter 06-4-2 메소드 호출 (0) | 2022.11.29 |