본문 바로가기
👨‍💻 2. 웹개발_Back end/2-1 Java

[JAVA] 10-2 예외 처리

by 달님🌙 2021. 8. 11.
반응형

 

컴파일시 일반 예외 vs 실행 예외 차이점

 

- 일반 예외가 발생할 가능성이 있는 코드는 빨간줄로 컴파일 에러를 발생시켜 예외처리 코드의 필요성을 알려줌

- 이 때 빨간 줄에 커서를 대면 Unhandled exception (처리되지 않은 예외)라고 뜬다.

- 실행 예외는 컴파일러가 그냥 넘겨버려서 컴파일에러는 뜨지않으므로 개발자가 경험을 토대로 예외 처리 코드를 작성해야한다.

 

예외 처리 코드 구조

 

try {
	예외 발생 가능성이 있는 코드 작성
} 

catch(예외클래스 e) {
	- 예외가 발생하지 않은 경우 : catch 블록은 실행되지 않음
    - 예외가 발생한 경우 : 즉시 실행을 멈추고 catch 블록의 예외 처리 코드 실행한 후 finally 블록 실행
    
} 

finally {
	- 생략 가능한 구역
    - 예외 발생 여부와 관계없이 항상 실행됨
    - try-catch 문에 return문이 있더라도 finally 블록은 항상 실행됨
}

 

 

일반 예외 처리 코드 예제 ( ClassNotFoundException )

 

- Class.forname() 메소드 : 매개값으로 들어온 클래스가 존재하는 클래스면 클래스의 객체를 리턴하고

  존재하지않으면 ClassNotFoundException 예외를 발생시킨다.

 

public class ClassNotFoundExceptionExample {
	public static void main(String[] args) {
		try {
			Class clazz = Class.forName("java.lang.String2");
		} catch(ClassNotFoundException e) {
			System.out.println("클래스가 존재하지 않습니다.");
		} 
	}
}
클래스가 존재하지 않습니다.

이 경우는 일반 예외의 경우라서 컴파일 에러가 났기떄문에 처리하기가 쉽다.

 

 

실행 예외 처리 코드 예제 ( ClassNotFoundException )

 

public class TryCatchFinallyRunTimeExceptionExample {
	public static void main(String[] args) {
		String data1 = null;
		String data2 = null;
		
		try {
			data1 = args[0];
			data2 = args[1];
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("실행 매개값의 수가 부족합니다.");
			return;
		}
		try {
			int value1 = Integer.parseInt(data1);
			int value2 = Integer.parseInt(data2);
			int result = value1 + value2;
			System.out.printf("%d + %d = %d\n", value1, value2, result);;
		} catch(NumberFormatException e) {
			System.out.println("숫자로 변환할 수 없습니다.");
		} finally {
			System.out.println("다시 실행하세요");
		}
		System.out.println("프로그램 종료");
	}
}

 

<바로 Run을 실행한 경우>

실행 매개값의 수가 부족합니다.

 

<Run Configurations를 통해 실행 매개 값으로 문자열을 준 경우>

숫자로 변환할 수 없습니다.
다시 실행하세요
프로그램 종료

 

<Run Configurations를 통해 실행 매개 값으로 숫자를 준 경우>

200 + 300 = 500
다시 실행하세요
프로그램 종료

 

<프롬프트 창에서 실행시킨 경우>

 

다중 catch 블록

 

public class CatchByExceptionKindExample {
	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.printf("%d + %d = %d\n", value1, value2, result);
		} catch(ArrayIndexOutOfBoundsException e) {
			System.out.println("실행 매개값의 수가 부족합니다.");
		} catch(NumberFormatException e) {
			System.out.println("숫자로 변환할 수 없습니다.");
		} finally {
			System.out.println("다시 실행하세요.");
		}
		System.out.println("프로그램을 종료합니다.");
	}
}

 

- 예외 발생 가능 코드가 여러 개면 try-catch문을 여러 개 작성하는 것이 아니라

- try 안에 모든 실행 코드를 넣어주고 catch를 여러 개 만들면 된다.

- 어차피 하나의 예외가 발생하면 즉시 실행을 멈추고 해당 catch 블록으로 가기 때문에 하나의 예외처리만 실행이 가능하다.

 

catch 순서

 

public class CatchOrderExample {
	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.printf("%d + %d = %d\n", value1, value2, result);
		} catch(ArrayIndexOutOfBoundsException e) {
			System.out.println("실행 매개값의 수 가 부족합니다.");
		} catch(Exception e) {
			System.out.println("실행에 문제가 있습니다.");
		} finally {
			System.out.println("다시 실행하세요.");
		} 	
		System.out.println("프로그램 종료");
	}
}

 

<매개값을 2개 받긴 했지만 숫자를 받지 않은 경우>

실행에 문제가 있습니다.
다시 실행하세요.
프로그램 종료

 

예외 떠넘기기

 

- 예외가 발생할 가능성이 있는 코드는 try - catch 블록으로 예외처리를 해주는 것이 원칙이지만

- throws [예외클래스] 형태로 예외를 떠넘길 수도 있다.

- 여기서 throws 가 사용된 메소드는 반드시 호출할 때에는 try-catch 문을 쓰거나 또다시 throws를 해야한다.

- 예를 들어 method2() 선언시 throws를 해주었다면 method2()를 호출하는 곳(method1)에서는 반드시 try-catch를 사용하여 try 블록안에서 메소드를 호출해야한다.

- 하지만 method1()에서도 try-catch문을 사용 안하고싶다면 또 method1 선언시 throws를 해주면 된다. 

- 그럼 이제 method1()을 호출하는 곳인 method0()에서는 반드시 try-catch문을 사용해주어야한다.

 

예외 떠넘기기 예제 - ClassNotFoundException

 

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");
	}
}
클래스가 존재하지 않습니다.

 

 

main() 메소드에서 throws Exception을 사용하면 안되는 이유

 

- 우선 main() 메소드에서도 throws로 예외를 떠넘길 수 있지만 그렇게되면 결국 JVM이 최종적으로 예외를 처리하게 됨

- 그런데 이는 사용자가 예외 내용을 알 수 없는 상태로 프로그램이 종료되므로 바람직하지 않다.

- 따라서 main() 메소드에서 try-catch 블록을 사용하여 최종적으로 예외 처리를 해주는 것이 바람직하다.

 

 

 

반응형

댓글