[JAVA] 예외 처리

dev_swanim·2023년 4월 18일

JAVA 문법

목록 보기
9/10
post-thumbnail

1. 예외와 예외 클래스

에러(error) : 컴퓨터 하드웨어의 고장으로 인해 응용프로그램 실행 오류 발생

예외(exception) : 잘못된 사용 또는 코딩으로 인한 오류

  • 일반 예외 (exception) : 컴파일러가 예외 처리 코드 여부를 검사하는 예외
  • 실행 예외 (Runtime Exception) : 컴파일러가 예외 처리 코드 여부를 검사하지 않는 에외

에러나 예외 둘 다 발생하면 프로그램이 곧바로 종료됨. 다만, 예외는 예외 처리를 통해 계속 실행 상태를 유지할 수 있음

자바는 예외가 발생하면, 예외 클래스로부터 객체를 생성한다. 객체는 예외 처리할 때 사용된다.

자바의 모든 에러와 예외 클래스는 Throwable을 상속받아 만들어지고, 추가적으로 예외 클래스는 java.lang.Exception 클래스를 상속받는다

실행 예외는 RuntimeException과 그 자식 클래스에 해당





2. 예외 처리 코드

try - catch - finally 블록으로 구성

  • try (예외 발생 가능 코드) - catch (try 블록에서 예외 발생 시, 실행됨. 예외가 발생하지 않으면 실행되지 않음) - finally (항상 실행되는 코드. 예외가 발생해도, 발생하지 않아도 실행됨)
public class ExceptionHandlingExample2 {
	public static void printLength(String data) {
		try {
			int result = data.length();
			System.out.println("문자 수: " + result);
		} catch(NullPointerException e) {
			System.out.println(e.getMessage()); //①
			//System.out.println(e.toString()); //②
			//e.printStackTrace(); //③
		} finally {
			System.out.println("[마무리 실행]\n");
		}
	}

	public static void main(String[] args) {
		System.out.println("[프로그램 시작]\n");
		printLength("ThisIsJava");
		printLength(null);
		System.out.println("[프로그램 종료]");
	}
}






3. 예외 종류에 따른 처리

다중 catch를 사용해 발생하는 예외에 따라 다양한 예외들을 예외 처리 코드로 다르게 작성할 수 있다.

  1. 각 예외 종류에 따라 다르게 작성 가능
try {
				int value = Integer.parseInt(array[i]);
				System.out.println("array[" + i + "]: " + value);
			} catch(ArrayIndexOutOfBoundsException e) {
				System.out.println("배열 인덱스가 초과됨: " + e.getMessage());
			} catch(NumberFormatException e) {
				System.out.println("숫자로 변환할 수 없음: " + e.getMessage());
			}



  1. 예외 클래스들이 상속 관계에 있을 경우, 하위 클래스 catch를 먼저 작성, 상위 클래스 catch를 나중에 작성
try {
				int value = Integer.parseInt(array[i]);
				System.out.println("array[" + i + "]: " + value);
			} catch(ArrayIndexOutOfBoundsException e) {
				System.out.println("배열 인덱스가 초과됨: " + e.getMessage());
			} catch(Exception e) {
				System.out.println("실행에 문제가 있습니다.");
			}



  1. 두 개 이상의 예외를 동시에 처리하고 싶을 경우 | (or)를 이용해 연결
try {
				int value = Integer.parseInt(array[i]);
				System.out.println("array[" + i + "]: " + value);
			} catch(ArrayIndexOutOfBoundsException e) {
				System.out.println("배열 인덱스가 초과됨: " + e.getMessage());
			} catch(NullPointerException | NumberFormatException e) {
				System.out.println("데이터에 문제가 있음: " + e.getMessage());
			}






4. 리소스 자동 닫기

  • 리소스(resource) : 데이터를 제공하는 객체
  • 리소스는 사용하기 위해 열어야(open)하고 사용이 끝난 후에는 닫아야(close)한다. 제대로 파일을 닫아야지만, 다른 프로그램에서도 사용할 수 있다.
FileInputStream fis = null;
try {
	fis = new FileInputStream("file.txt"); //파일 열기
}catch(IOException e){
} finally{
	fis.close(); //파일 닫기
}



public class FileInputStream implements AutoCloseable{
	
	@override
	public void close() throws Exceptions {...}
}
try(FileInputStream fis = new FileInputStream("file.txt")){

} catch(IOException e){

}

try-with-resources를 이용해 하면 더 간단하다. try 괄호에 리소스를 여는 코드를 작성하는 것이다.






5. 예외 떠넘기기

메소드 내부에서 예외가 발생할 때 try-catch 블록으로 처리하는 게 일반적이지만, 메소드를 호출한 곳으로 throws를 사용해 예외를 떠넘길 수 있다.

public class ThrowsExample1 {
	public static void main(String[] args) {
		try {
			findClass();
		} catch(ClassNotFoundException e) { //호출한 곳에서 예외처리
			System.out.println("예외 처리: " + e.toString());
		}
	}

	public static void findClass() throws ClassNotFoundException {
		Class.forName("java.lang.String2");
	}
}
public class ThrowsExample2 {
	public static void main(String[] args) throws Exception {
		findClass();
	}

	public static void findClass() throws ClassNotFoundException {
		Class.forName("java.lang.String2");
	}
}

나열할 예외 클래스가 많으면 throws Exception 또는 throws Throwable 만으로 모든 예외를 간단히 떠넘길 수 있다.






6. 사용자 정의 예외

  • 사용자 정의 예외 : 사용자가 직접 예외 클래스를 정의해 사용하는 것


사용자 정의 예외

일반 예외, 실행 예외 선언 둘 다 가능하다

일반 예외는 Exception의 자식 클래스로 선언, 실행 예외는 RuntimeException의 자식 클래스로 선언

public class InsufficientException extends Exception { //일반 예외로 선언
	public InsufficientException() {
	}

	public InsufficientException(String message) { //두 개의 생성자 선언
		super(message);
	}
}



예외 발생 시키기

public class Account {
	private long balance;
	
	public Account() { }

	public long getBalance() {
		return balance;
	}
	public void deposit(int money) {
		balance += money;
	}
	public void withdraw(int money) throws InsufficientException {
		if(balance < money) {
			throw new InsufficientException("잔고 부족: "+(money-balance)+" 모자람");
		}
		balance -= money;
	}
}
public class AccountExample {
	public static void main(String[] args) {
		Account account = new Account();
		//예금하기
		account.deposit(10000);
		System.out.println("예금액: " + account.getBalance());

		//출금하기
		try {
			account.withdraw(30000);
		} catch(InsufficientException e) {
			String message = e.getMessage();
			System.out.println(message);
		}
	}
}






📚참고 문헌

이것이 자바다(신용권, 임경균 지음)

profile
데이터와 백엔드를 공부하고 있습니다😌

0개의 댓글