ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java의 Exception
    Java/이론&문법 2023. 9. 15. 02:31

    예외란?

    • An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions (Oracle Docs) 
    • 예외란 프로그램의 실행동안 발생되는 것으로, 프로그램 명령어들의 정상적인 흐름을 방해하는 것을 의미합니다. 

    Try - Catch - Finally

    • 예외가 발생한 경우
      • try 내에서 발생한 이후의 문장들은 실행되지 않음
      • catch 내에 있는 문장은 실행되고, try-catch 문 이후의 내용이 실행 
    • 예외가 발생하지 않은 경우
      • try 문이 쭉 실행되고, catch 내에 있는 문장은 실행되지 않음.
    • finally는 예외 발생 여부와 상관없이 실행되는 문장이다. 
    • try 블록 내에서 선언한 변수는 try 블록 내에서만 사용이 가능하다.  

    Catch 블록은 순서를 따진다. 

    • Exception이 예외의 가장 최상위인 만큼, 마지막 catch 블록에 넣어주어야 한다. 
      • 아래 코드는 NullPointerException을 발생시킨다. 
    public static void main(String[] args) {
            int[] arr = new int[5];
            try {
                arr = null;
                System.out.println(arr[2]);
            } catch (NullPointerException e) {
                System.out.println("NullPointerException");
            } catch (Exception e) {
                System.out.println("ERROR");
            }
    }
    • 만약 아래처럼 순서를 바꾸면 어떨까?
     public static void main(String[] args) {
            int[] arr = new int[5];
            try {
                arr = null;
                System.out.println(arr[2]);
            } catch (Exception e) {
                System.out.println("ArrayIndexOutOfBounds");
            } catch (NullPointerException e) {
                System.out.println("NullPointerException");
            } 
    }
    • try문 다음에 오는 catch 블록은 1개 이상 올 수 있으며, 먼저 선언한 catch 블록의 예외 클래스가 다음에 선언된 catch 블록 예외의 부모라면, 자식에 속하는 catch는 실행될 일이 없으므로 컴파일이 되지 않는다.
    • Exception 클래스가 모든 예외의 부모이므로 발생하는 현상.
    • 하나의 try 블록에서 예외가 발생하면 그 예외와 관련이 있는 catch 블록을 찾아서 실행한다. 
    • 발생한 예외와 관련있는 catch 블록이 없다면, 예외가 발생되고 끝나므로 마지막에 Exception 으로 묶어주는 습관을 들일 것. 

     


    예외의 종류

     

     

     

    Error

    • 자바 프로그램 밖에서 발생한 예외
    • Exception 클래스와의 가장 큰 차이는 프로그램 안에서 발생했는지, 밖에서 발생했는 지의 여부이다. 
    • 또한 프로그램이 멈추어 버리는(프로세스에 영향을 주는) 것이 Error이다. 
      • Exception 클래스는 에러가 아니며, Exception은 스레드에만 영향을 주어 계속 실행이 가능하다. 

     

    Runtime Exception ( == Unchecked Exception )

    • 예외가 발생할 것을 미리 감지하지 못했을 때 발생
    • Runtime Exception을 확장한 예외들이다. 
    • 컴파일 시에 체크하지 않기 때문에 unchecked Exception이라고도 부르는 것 

     

    Checked Exception

    • Exception 클래스의 하위 클래스 중 Runtime Exception을 제외한 나머지 
    • 컴파일러가 예외 처리를 확인한다. (컴파일 단계에서 잡힌다)
    • 반드시 예외 처리가 되어야 한다.
      • ex) IO의 경우, 무조건 throws IOException 을 main에 달아줘야 하는 등..

     

    Throwable 

    • 위 그림에서 보면 알 수 있듯, Exception과 Error의 공통 부모 클래스들은 Throwable이다. 
      • 즉, Exception, Error 모두 상위 클래스인 Throwable로 처리가 가능하다! 
    • Exception, Error의 성격은 다르지만, 동일한 이름의 메소드를 사용하여 처리할 수 있도록 하기 위함이다. 
    • Throwable의 생성자는 아래와 같다. 
    public Throwable() {
    	fillInStackTrace();
    }
    
    public Throwable(String message) {
    	fillInStackTrace();
    	detailMessage = message;
    }
    
    public Throwable(String message, Throwable cause) {
    	fillInStackTrace();
    	detailMessage = message;
    	this.cause = cause;
    }
    
    public Throwable(Throwable cause) {
    	fillInStackTrace();
    	detailMessage = (cause==null ? null : cause.toString());
    	this.cause = cause;
    }

     

    • Throwable 내부에 작성된 메소드 (이것보다 더 많지만 일부만 발췌)
    public String getMessage() // 예외 메시지를 String 형태로 제공받음
    
    public String toString() // getMessage보다 더 자세한 형태의 메시지(예외클래스 이름까지)
    
    public synchronized Throwable fillInStackTrace()
    // 코드 내부에서 private native Throwable fillInStackTrace(int dummy) 호출
    
    public void setStackTrace(StackTraceElement[] stackTrace)
    
    public void printStackTrace(PrintWriter s) // 메소드들의 호출관계 출력

     

     


    Throws Exception 

     

    • try 문 안에서 throw new Exception ~ 을 통해 예외를 발생시킨다. 
      • 개발자가 예외 클래스의 객체를 생성, try 문 이후는 실행되지 않고 catch 문으로 넘어간다.
      • catch 블록에서 해당하는 예외가 있다면 (동일하거나, 상속 관계에 있는 예외가 있다면) 해당 catch 블록에서 처리 
      • catch 블록에서 해당하는 예외가 없다면 메소드 밖으로 예외를 던진다. (예외가 발생한 메소드를 호출한 메소드로 처리를 위임)
      • 대신, 이 예외가 발생한 메소드가 메소드 밖으로 예외를 던진다면, 걔를 호출한 메소드가 try-catch로 묶어서 처리 해 줘야 한다. 
    • 예시코드
      • throwsException 은 자기를 호출한 main에 예외 처리를 위임
      • main(예외발생 메소드를 호출한 메소드) 메소드는 try-catch로 감싸서 이 예외를 처리한다. (안 그러면 컴파일 안됨)
    public static void main(String[] args) {
        try {
        	// ... 
           throwsException(13);
        } catch (Exception e) {
        	// ...
        }
    }
    
    public void throwsException(int num) throws Exception {
    	if (num > 12) {
        	throw new Exception("~~~");
        }
    }

     


    Throwable 또는 Exception 상속 받아 예외를 직접 만들수도 있다. 

     

    • 예시 코드 
    public class MyException extends Exception {
        public MyException() {
        	super();
        }
        
        public MyException(String Message) {
        	super(message);
        }
    }
    
    // 실제 사용한다면
    public void throwMyException() throws MyException {
        try {
        	if (num > 12) {
            	throw new MyException("Number is Over");
            }
        } catch (MyException e) {
        	e.printStackTrace();
        }
    }

     

    • 추가적인 예외 처리 전략
      • 임의의 예외 클래스를 위처럼 만든다면, try-catch로 묶어줄 필요가 있을 때만 Exception 클래스를 확장한다.
        • Runtime Exception은 해당 메소드를 호출하는 애만 try-catch로 잡고, 메소드 자체는 try-catch 안 사용해도 된다.
      • 일반적으로 실행 시 예외를 처리할 수 있는 경우에는 RuntimeException 클래스를 확장하는 것을 권장한다.
      • catch문 내에는 꼭 로그 처리와 같은 예외 처리를 해줄 것(예외 분석이 어려워지지 않도록)

     

     

    기타 참고 자료 

    더보기

    자바의 신 1권 14장

    Oracle Docs

    'Java > 이론&문법' 카테고리의 다른 글

    Annotation  (0) 2023.09.15
    Nested Class  (0) 2023.09.15
    Interface, abstract class, enum  (0) 2023.09.10
    자바의 상속, Object 클래스  (0) 2023.09.10
    JVM 구성, 동작 방식  (0) 2023.09.01
Designed by Tistory.