자바/기본적인 개념

예외처리(1)

백_곰 2021. 12. 16. 11:55

1. 자바에서의 에러 종류 3가지

(1) 컴파일 에러

: 컴파일러가 빨간줄로 표시해주며 자바 문법에 어긋날 경우 발생하는 에러이다.

( 예) 명시적 형변환이 없을 경우 등 )

 

(2) 런타임 에러

: 컴파일 에러는 발생하지 않지만 프로그램 실행 후 발생하는 에러이다.

( 예) 범위에 벗어나는 인덱스 참조 등 )

 

(3) 논리적 에러

: 실행은 잘 되지만, 의도와 다르게 동작하는 것을 말한다.

 

 

 

2. 에러 vs 예외

(1) 에러: 메모리 부족(OutOfMemoryError)와 스택오버플로우(StackOverflowError) 같은 복구할 수 없는 심각한 오류

 

(2) 예외: 발생하더라도 수습될 수 있는 덜 심각한 예외

 

 

 

3. 예외 클래스의 계층 구조

( Exception 클래스들은 주로 외부의 영향으로 발생하는 것으로, 프로그램의 사용자가 주범이다. )

--> 존재하지 않는 파일 이름을 입력(FileNotFoundException)

--> 실수로 클래스의 이름을 잘못 입력(ClassNotFoundException)

--> 입력한 데이터 형식이 잘못된 경우(DataFormatException)

 

( RuntimeException 클래스들은  주로 프로그래머의 실수에 의해서 발생되는 예외들을 잡아준다. )

--> 배열 범위 오류(ArrayIndexOutOfBoundsException)

--> 값이 null인 참조 변수의 멤버 호출(NullPointerException)

--> 클래스간의 형변환을 잘못된 경우(ClassCastException)

 

 

 

4. 예외처리하기(try-catch 문)

- 프로그램 도중 에러는 어쩔 수 없지만, 예외는 프로그래머가 처리할 수 있어야 한다.

 

- 발생된 예외를 처리하지 못하면, 프로그램은 비정상적으로 종료되며 처리되지 못한 예외는

JVM의 '예외처리기(UncaughtExceptionHandler)'가 받아서 예외의 원인을 화면에 출력한다.

 

- catch문에서 선언된 변수는 catch 블럭 내에서만 유효하다.

 

- 이중 try-catch문을 사용한다면, catch의 참조변수는 중복돼서는 안된다.

 

 

( 위에서 말했듯이 중복 e를 쓰게 되면, 16번쨰 줄처럼 오류가 발생하게 된다. )

 

 

 

5. 이해를 돕기 위한 예제(1)

: ArithmeticException 예외 클래스를 알아보는 예제이다.

( 0을 나누는 것에 방지를 위해 예외를 두었다. )

 

 

 

6. 이해를 돕기 위한 예제(2)

: 하나의 try와 두 개의 catch를 하는 동시에 부모와 자식의 관계를 확인하는 예제이다.

( 12번째 줄에서 instanceof을 사용했는데, true가 나왔다. 그 이유는 위에서의 상속 계층도에 있다. )

( 15번째 줄에서의 catch(Exception e)는 위에서 catch한 ArithmeticException을 제외한 모든 예외를 처리한다. )

 

 

 

7. printStackTrace()와 getMessage()

- 예외가 발생했을 때 생성되는 예외 클래스의 인스턴스에는 발생한 예외 정보가 담겨있다.

 

(1) printStackTrace(): 예외발생 당시의 호출스택에 있었던 메서드의 정보와 예외 메시지를 화면에 출력한다.

(2) getMessage(): 발생한 예외 클래스의 인스턴스에 저장된 메시지를 얻을 수 있다.

 

 

 

8. 멀티 catch 블럭

( 7번째 줄처럼 catch를 두번 쓰지 않고 바로 '|' 기호를 넣고 써도 된다. )

 

( 그러나 현재 오류가 나는 이유는 조상과 자손의 관계이기 때문이다. )

( 즉, 어짜피 똑같이 예외를 잡는 것을 불필요하게 코드를 사용하지 말라는 의미를 주는 것이다. )

 

( 그렇다면, 아래의 코드처럼 공통 부모를 가지고 서로 관련없는 예외클래스를 사용해야 할 것이다. )

 

( 이때, |로 연결된 예외 클래스들의 참조변수 e는 공통 조상인 Exception에 관한 멤버만 사용할 수 있다. )

( 만약 ExceptionA에 대한 멤버를 사용하고 싶다면, 저렇게 instanceof를 한 다음 형변환을 해줘야 한다. )

 

 

 

9. 예외 발생시키기

- 프로그래머가 키워드 throw를 사용해서 고의로 예외를 발생시킬 수 있다.

 

- 하는 방법

(1) 먼저 연산자 new를 이용해서 발생시키려는 예외 클래스의 객체를 만든 다음

Exception e = new Exception("고의로 발생시킴");

 

(2) 키워드 throw를 사용해서 예외 발생시킨다.

throw e;

 

 

 

10. 이해를 돕기 위한 예제(2)

: 9번 내용을 이해하기 위한 예제이다.

 

 

11. 이해를 돕기 위한 예제(3)

: Exception vs RuntimeException

( 위 코드에서 컴파일 에러가 나는 이유는 에러가 나는데 예외를 처리하는 부분이 비어있기 때문이다. )

 

( 그러나 아래의 코드는 다르다. )

( 그 이유는 프로그래머의 실수로 발생하는 예외이기에 예외처리를 강제로 하지 않아도 되는 것이다. )

 

( 컴파일러가 예외처리를 확인하지 않는 RuntimeException 클래스들은 'unchecked예외' 라고 부른다. )

( 컴파일러가 예외처리를 확인하는 Exception 클래스들은 'checked예외' 라고 부른다. )

 

 

11. 메서드에 예외 선언하기.

- 메서드에 예외를 선언하면, 이 메서드에는 예외가 발생할 수 있는 것을 예측 할 수 있게 된다.

 

- void method() throws Exception1, Exception2 ...{

                     //메서드 내용

  }

으로 사용할 수 있다.

 

- 아래의 코드를 사용한다면, 모든 조상인 Exception 클래스를 사용하는 것이므로, 

자손 타입의 예외까지도 발생할 수 있다.

 

 

12. 이해를 돕기 위한 예제(4)

: 11번을 내용을 이해하기 위한 예제이다. 

 

( 위 코드의 처리 순서는 다음과 같다. )

( 예외 발생 지점은 method2()이고, method2()에는 try-catch문이 없다. )

( 그래서 자신을 호출한 method1()에게 다시 예외를 넘겨준다. )

( 그러나 method1()에서도 try-catch문이 없기 때문에, main을 또 다시 넘겨준다. )

( main 또한 없기 때문에 비정상적으로 종료된다. )

 

( 그렇기 때문에 try-catch를 해주는 구문을 반드시 넣어야지 정상적으로 실행된다. )

( 아래의 코드를 보고 이해하자. )