ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 혼공자 : ch10 예외처리
    Java 2023. 2. 23. 11:02

    10-2 예외처리

     

    예외 : 사용자 조작 실수, 개발자 코딩 문제 발생 오류

              예외가 발생하면 프로그램 종료.

              > 정상 실행 상태 유지를 위해 예외처리


    예외 처리 코드

    예외 처리 코드 : try - catch - finally 블록

    1. try 블록에는 예외 발생 가능 코드가 위치한다.
    2. try 블록의 코드가 예외 발생 없이 정상 실행되면 catch() 블록의 코드를 스킵하고 finally 블록의 코드를 실행한다. 만약 try 블록에서 예외가 발생하면 즉시 실행을 멈추고 catch() 블록으로 이동하여 예외 처리 코드를 실행한다. 그리고 finally 블록의 코드를 실행한다.
    3. finally 블록은 생략 가능하며, 예외 발생 여부와 상관없이 항상 실행할 내용이 있을 경우에만 finally 블록을 작성해준다. 심지어 try, catch() 블록에서 return문을 사용해도 finally 블록은 실행된다

    예외 처리하지 않는 경우

    try - finally

     

    예외 처리하는 경우

    try 즉시 정지 - catch( 예외클래스 e ) - finally


    예제) 일반 예외 처리

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

    - Class이름의 class가 패키지 내부에 존재하지 않기 때문에 ClassNotFoundException 예외가 발생했다.


    예제) 실행 예외 처리

    public class TryCatchFinallyRuntimeExceptionExample {
    	public static void main(String[] args) {
    		String data1 = null;
    		String data2 = null;
    
    		data1 = args[0];
    		data2 = args[1];
    
    		System.out.println(data1);
    		System.out.println(data2);
    	}
    
    }
    
    // 발생 예외 java.lang.ArrayIndexOutOfBoundsException

    - args 배열에 실행 매개값이 저장되지 않았기 때문에 Sysout(data) 실행어를 수행하지 못 하고 ArrayIndexOutOfBoundsException 예외가 발생했다.

     

    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.println(result);
    		}catch(NumberFormatException e) {
    			System.out.println("숫자로 변환할 수 없습니다.");
    		}finally {
    			System.out.println("다시 실행하세요.");
    		}
    	}
    
    }

    - ArrayIndexOutOfBoundsException 을 try - catch로 처리했다.

    그리고 2개의 실행 매개값을 입력 했을 때, 숫자가 아닌 문자를 주고 실행했을 때 발생한

    NumberFormatException 예외도 try - catch로 처리해줬다.

     

    - 해당 예제를 실행하면서 ArrayIndexOutOfBoundsException , NumberFormatException 에 오류가 발생했다.

    예외 코드의 경우 Class 형태로 저장 되는데, 같은 패키지 내부에 동일한 이름의 java 파일을 생성해서 발생한 오류였다.

    java 파일을 생성할 때 가능한 예외 코드와 비슷한 이름을 짓지 말자.


    예외 종류에 따른 처리 코드

    다중 catch

     : try 블록 내부는 다양한 예외가 발생할 수 있다. 이것에 대한 해답은 다중 catch 블록을 작성하는 것이다.

    하나의 try 블록에 여러개의 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.println(result);
    		}catch(ArrayIndexOutOfBoundsException e) {
    			System.out.println("실행 매개값의 수가 부속합니다.");
    		}catch(NumberFormatException e) {
    			System.out.println("숫자로 변환할 수 없습니다.");
    		}finally {
    		System.out.println("다시 실행하세요.");
    		}
    	}
    }

    - 앞에서 처리했던 예외 2개를 하나의 try 블록에서 발생하게 만든 후, catch() 블럭을 2개 생성해서 예외를 처리했다.


    catch 순서

     : 다중 catch 블록을 작성할 때 주의할 점은 상위 예외 클래스가 하위 예외 클래스보다 아래쪽에 위치해야 한다는 것이다.

    만약 상위 예외 클래스의 catch 블록이 위에 있다면, 하위 예외 클래스의 catch 블록은 실행되지 않는다.

    하위 예외는 상위 예외를 상속했기 때문에, 상위 예외 타입도 되기 때문이다.

    		catch(Exception e) {
    			System.out.println("실행 매개값의 수가 부속합니다.");
    		}catch(NumberFormatException e) {
    			System.out.println("숫자로 변환할 수 없습니다.");
    		}

    - 이전 예제에서 일부분을 가져왔다. Exception 클래스는 모든 예외들의 최상위 클래스이기 때문에 Exception 이후에 등장하는 catch 블럭은 작동하지 않는다.

    - java.lang.Exception 클래스 아래에 일반 예외와 java.lang.RuntimeException(실행 예외)클래스 가 있으므로 실행 예외 catch() 블록 작성 후 일반 예외 catch() 블록을 작성하면 catch() 블록을 적절하게 사용할 수 있겠다.


    예외 떠넘기기

    throws 키워드

     : 메소드 내부에서 예외가 발생할 경우 try-catch 블록으로 처리하는 것이 기본이지만, 메소드를 호출한 곳으로 예외를 떠넘길 수도 있다.

    throws 키워드는 메소드 선언부 끝에 작성되어 메소드에서 처리하지 않은 예외를 호출한 곳으로 떠넘기는 역할을 한다.

    떠넘길 예외 클래스를 쉼표로 구분해서 나열해주면 된다.

    리턴타입 메소드이름(매개변수, ...) throws 예외클래스1, 예외클래스2, ... {
    }

    - 다음과 같이 예외의 종류별로 throws 뒤에 나열하는 것이 일반적이지만,

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

    - Exception으로 모든 예외를 한번에 넘길 수도 있다.

     

    예제)

    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");
    	}
    }

     - try-catch 블록이 없다면, findClass() 에서 일반 예외 (ClassNotFoundException)가 발생한다. 일반적으로 findClass() 메소드 내부에서 try-catch블록으로 예외처리하겠지만, 메서드 호출부로 예외를 넘긴 케이스다.

     

    *주의사항

     : throws 키워드가 붙어있는 메소드는 반드시 try 블록 내에서 호출되고 catch 블록에서 떠넘겨 받은 예외를 처리해야한다.

    자바 API 도큐먼트를 보면 클래스 생성자와 메소드 선언부에 throws 키워드가 붙어 있는 것을 흔히 볼 수 있다.

    이러한 생성자와 메소드를 사용하고 싶다면, 반드시 try-catch 블록으로 예외 처리를 하거나 throws를 다시 사용해서 예외를 호출한 곳으로 떠넘겨야한다.

     

    자바 도큐먼트 예시)

    forName
    public static Class<?> forName(String className) throws ClassNotFoundException

     

    'Java' 카테고리의 다른 글

    배열 선언하기  (0) 2023.05.11
Designed by Tistory.