10. 예외 처리

Bummy·2023년 10월 29일
0

JAVA

목록 보기
10/11
post-thumbnail

10.1 예외와 예외 클래스

  • 에러 : 컴퓨터 하드웨어의 오동작 또는 고장으로 인해 응용프로그램 실행 오류가 발생하는 것
  • 예외 : 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인해 발생하는 프로그램 오류
    • 예외에는 일반 예외, 실행 예외 두가지가 있다.
    • 일반 예외는 컴파일러 체크 예외라고도 하는데, 자바 소스를 컴파일하는 과정에서 예외 처리 코드가 필요한지 검사하기 때문

10.2 실행 예외

  • 실행 예외는 자바 컴파일러가 체크를 하지 않기 때문에 오로지 개발자의 경험에 의해서 예외 처리 코드를 삽입해야한다.

10.2.1 NullPointerException

  • 객체 참조가 없는 상태, 즉 null 값을 갖는 참조 변수로 객체 접근 연산자인 도트를 사용했을 때 발생한다.
  • 객체가 없는 상태에서 객체를 사용하려 했으니 예외가 발생하는 것
public class NullPointerExceptionExample{
	public static void main(String[] args){
		String data = null;
		System.out.println(data.toString());
	}
}

10.2.2 ArrayIndexOutOfBoundsException

  • 배열에서 인덱스 범위를 초과하여 사용할 경우 실행 예외인 ArrayIndexOutOfBoundsException이 발생한다.
public class ArrayIndexOutOfBoundsExceptionExample{
	public static void main(String[] args){
		String data1 = args[0];
		String data2 = args[1];

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

→ 실행 매개값을 주지 않았기 때문에 args[0], args[1]과 같이 인덱스를 사용할 수 없다.

10.2.3 NumberFormatException

  • 숫자로 변환될 수 없는 문자열을 숫자로 변환하려고 하면 발생하는 예외
public class NumberFormatException{
	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);
	}
}		

10.2.4 ClassCastException

  • 타입 변환(casting)은 상위 클래스와 하위 클래스 간에 발생하고 구현 클래스와 인터페이스 간에도 발생한다.
  • 이러한 관계가 아니면 클래스는 다른 클래스로 타입 변환할 수 없다.
  • 억지로 타입 변환을 시도할 경우 ClassCastException이 발생한다.
Animal animal = new Dog();
if(animal instanceof Dog){
	Dog dog = (Dog) animal;
}else if(animal instanceof Cat){
	Cat cat = (Cat) animal;
}
💡 ClassCastException을 발생시키지 않으려면 타입 변환 전에 타입 변환이 가능한지 instanceof 연산자로 확인하는 것이 좋다.

10.2 예외 처리 코드

  • 프로그램에서 예외가 발생했을 경우 프로그램의 갑작스러운 종료를 막고, 정상 실행을 유지할 수 있도록 처리하는 코드를 예외 처리 코드라고 한다.
  • 실행 예외는 컴파일러가 체크해주지 않기 때문에 예외 처리 코드를 개발자의 경험을 바탕으로 작성해야 한다.
  • 예외 처리 코드는 try-catch-finally 블록을 이용한다.
try{
	//예외 발생 가능 코드
} catch(예외클래스 e){
	//예외 처리
} finally {
	//항상 실행;
}
  • try 블록에는 예외 발생 가능 코드가 위치한다.
  • try 블록의 코드가 예외 발생 없이 정상 실행되면 catch 블록의 코드는 실행되지 않고 finally 블록의 코드를 실행한다.
  • try 블록에서 예외가 발생하면 즉시 실행을 멈추고 catch 블록으로 이동하여 예외 처리 코드를 실행한다.
  • finally 블록은 생략 가능하며, 예외 발생 여부와 상관없이 항상 실행할 내용이 있을 경우에만 finally 블록을 작성해주면 된다.

10.4 예외 종류에 따른 처리 코드

10.4.1 다중 catch

  • 발생되는 예외별로 예외 처리 코드를 다르게 하려면 다중 catch 블록을 작성한다.
  • try 블록에서 해당하는 타입의 예외가 발생하면 catch 블록을 실행하도록 되어 있다.
try{
	//ArrayIndexOutOfBoundException 발생

	//NumberFormatException 발생
} catch(ArrayIndexOutOfBoundException e){
	//예외 처리 1
} catch(NumberFormatException e){
	//예외 처리 2
}
  • catch 블록이 여러 개라 할지라도 단 하나의 catch 블록만 실행된다.

10.4.3 catch 순서

  • 다중 catch 블록을 작성할 때 주의할 점은 상위 예외 클래스가 하위 예외 클래스보다 아래쪽에 위치해야 한다.
  • try 블록에서 예외가 발생하면 예외를 처리해줄 catch 블록은 위에서부터 차례대로 검색된다.
  • 상위 예외 클래스의 catch 블록이 위에 있다면 하위 예외 클래스의 catch 블록은 실행되지 않는다.
try{
	//ArrayIndexOutOfBoundException 발생

	//NumberFormatException 발생
} catch(Exception e){
	//예외 처리1
} catch(ArrayIndexOutOfBoundException e){
	//예외 처리2 (X)
}

-> 수정된 코드
try{
	//ArrayIndexOutOfBoundException 발생

	//NumberFormatException 발생
} catch(ArrayIndexOutOfBoundException e){
	//예외 처리1
} catch(Exception e){
	//예외 처리2 
}

→ 수정된 코드는 ArrayIndexOutOfBoundException가 발생하면 첫 번째 catch 블록을 실행하고, 그 밖의 다른 예외가 발생하면 두 번째 catch 블록을 실행한다.

10.4.3 멀티 catch

  • 하나의 catch에서 여러 개의 예외 를 처리할 수 있도록하는 기능
try{
	//ArrayIndexOutOfBoundException 또는 NumberFormatException 발생

	// 다른 예외 발생
} catch(ArrayIndexOutOfBoundException | NumberFormatException  e){
	//예외 처리1
} catch(Exception e){
	//예외 처리2 
}

10.5 자동 리소스 닫기

  • 자바 7에서 새로 추가된 try-with-resources 사용하면 예외 발생 여부와 상관없이 사용했던 리소스 객체의 close() 메소드를 호출해서 안전하게 리소스를 닫아준다.
FileInputStream fis = null;
try{
	fis = new FileInputStream("file.txt");

	...
 }catch(IOException){
	...
}finally{
	if(fis != null){
		try{
			fis.close();
		}catch(IOException e){
	}
}
//자바 6까지 사용했던 코드
  • 자바7에서 추가된 try-with-resource를 사용하면 close()를 명시적으로 호출하지 않아도 된다.

try-with-resource를 사용하기 위한 조건

  • 리소스 객체는 java.lang.AutoCloseable 인터페이스룰 구현하고 있어야한다.

10.6 예외 떠넘기기

  • 메소드 내부에서 예외가 발생할 수 있는 코드를 작성할 대 try-catch 블록으로 예외를 처리하는 것이 기본이지만, 경우에 따라서는 메소드를 호출한 곳으로 예외를 떠넘길 수도 있다.
  • 이때 사용하는 키워드는 throws이다.
  • throws 키워드는 메소드 선언부 끝에 작성되어 메소드에서 처리하지 않은 예외를 호출한 곳으로 떠넘기는 역할을 한다.
  • throws 키워드 뒤에는 떠넘길 예외 클래스를 쉼표로 구분해서 나열해주면 된다.
리턴타입 메소드명(매개변수, ...) throws 예외클래스1, 예외클래스2, ...{

}

// 발생할 수 있는 예외 종류별로 throws 뒤에 나열하는 것이 일반적이지만 Exception으로 대체할 수도 있다.

리턴타입 메소드명(매개변수, ...) throws Exception {

}
  • throws 키워드가 붙어있는 메소드는 반드시 try 블록 내에서 호출되어야 한다.
  • catch 블록에서 떠넘겨 받은 예외를 처리해야한다.
public void method1(){
	try{
		method2();
	}catch(ClassNotFoundException e){
		//예외 처리 코드
		System.out.println("클래스가 존재하지 않습니다.");
	}
}

public void method2() throws ClassNotFoundException { //호출한 곳에서 예외 처리
	Class clazz = Class.forName("java.lang.String2");
}

10.7 사용자 정의 예외와 예외 발생

  • 프로그램을 개발하다 보면 자바 표준 API에서 제공하는 예외 클래스만으로는 다양한 종류의 예외를 표현할 수 없다.
  • 애플리케이션 서비스와 관련된 예외를 애플리케이션 예외(Application Exception)라고 한다.
  • 애플리케이션 예외는 개발자가 직접 정의해서 만들어야 하므로 사용자 정의 예외라고도 한다.

10.7.1 사용자 정의 예외 클래스 선언

  • 사용자 정의 예외 클래스는 컴파일러가 체크하는 일반 예외로 선언할 수도 있고, 컴파일러가 체크하지 않는 실행 예외로 선언할 수도 있다.
  • 일반 예외로 선언할 경우 Exception을 상속하면 되고, 실행 예외로 선언할 경우에는 RuntimeException을 상속하면 된다.
public class XXXException extends [Exception | RuntimeException]{
	public XXXException(){}
	public XXXException(String message){super(message);}
}
  • 사용자 정의 예외 클래스 이름은 Exception으로 끝나는 것이 좋다.
  • 사용자 정의 예외 클래스도 필드, 생성자, 메소드 선언들을 포함할 수 있지만 대부분 선언만을 포함한다.
  • 생성자를 두 개를 선언하는 것이 일반적인데 하나는 변수가 없는 기본 생성자이고, 다른 하나는 예외 발생 원인(예외 메시지)을 전달하기 위해 String 타입의 매개 변수를 갖는 생성자이다.

10.7.2 예외 발생시키기

throw new XXXException();
throw new XXXException("메시지");
  • 예외 객체를 생성할 때는 기본 생성자 또는 예외 메시지를 갖는 생성자 중 어떤 것을 사용해도 된다.
  • 만약 catch 블록에서 예외 메시지가 필요하다면 예외 메시지를 갖는 생성자를 이용해야 한다.

10.8 예외 정보 얻기

  • try 블록에서 예외가 발생되면 예외 객체는 catch 블록의 매개 변수에서 참조하게 되므로 매개 변수를 이용하면 예외 객체의 정보를 알 수 있다.
  • 그 중 가장 많이 사용되는 메소드는 getMessage()와 printStackTrace()이다.
} catch(Exception e){
	String message = e.getMessage();
}
  • 이렇게 getMessage() 메소드의 리턴값을 이용해서 예외 메시지를 얻을 수 있다.

0개의 댓글