╱╱╭╮╱╱╱╱╱╱╭━━━╮╱╱╱╭╮╱╭╮╱╱╱╱╱╱ ╱╱┃┃╱╱╱╱╱╱┃╭━╮┃╱╱╱┃┃╱┃┃╱╱╱╱╱╱ ╱╱┃┣━━┳━━╮┃┃╱┃┣━╮╱┃╰━╯┣━━┳━╮╱ ╭╮┃┃╭╮┃┃━┫┃╰━╯┃╭╮╮┃╭━╮┃╭╮┃╭╮╮ ┃╰╯┃╭╮┃┃━┫┃╭━╮┃┃┃┃┃┃╱┃┃╭╮┃┃┃┃ ╰━━┻╯╰┻━━╯╰╯╱╰┻╯╰╯╰╯╱╰┻╯╰┻╯╰╯

Java/Java 기초

[Java] 예외처리 (Exception)

재안안 2022. 5. 1. 04:56

실제로 자바를 사용해서 코딩을 하다보면 오류가 생길 때 마다 콘솔에 Exception이 뜨며 프로그램이 종료된다.

자바에선 이런 오류들을 종류별로 구분하여 구체적으로 어떠한 오류가 발생했다라고 알려준다.

 

이런 오류들의 종류로 대표적인 예를 들자면 아래와 같이 있다.

  • NullPointerException
  • ArrayIndexOutOfBoundsException
  • ArithmeticException
  • IOException

 

이클립스는 콘솔을 통해 코드 내부에서 어떤 오류가 어디서 발생했는지 알려준다.

프로그래머 입장에서는 이렇게 친절하게 알려주니 그저 참고할 수 있는 노트로 생각하는 경우가 많다.

 

그런데 사실 프로그램의 오류는 프로그램 내부에서 발생하지 않을 수도 있다.

이를 버그라고 하며 프로그램 외부에서 발생하는 오류를 디버그라고 한다.

 

우선 Exception에 대해 알아보겠다.

 

Exception 상속 관계 표현

 

 

결국 프로그램 에러를 알려주는 Exception도 하나의 클래스라는 것을 알 수 있다. (Object Class 상속)

Exception도 하나의 클래스임을 기억하면 좋겠다.

 

프로그래밍중에 발생하는 Error들은 모두 RuntimeException을 상속한 Exception들이다.

ArithmeticException 어떤 수를 0으로 나눌려고할 때 콘솔에 출력
NullPointerException 정의되지 않은 주소를 참조할 때 콘솔에 출력
ArrayIndexOutOfBoundsException 잘못된 배열의 인덱스를 참조할 때 콘솔에 출력

 

프로그램에서 Error가 발생하면 Exception을 출력하고 프로그램은 종료된다.

출력된 Exception을 통해 어디서 어떤 Error가 발생했는지 참고한다고 했는데

 

이때 프로그램을 종료시키지 않을 방법이 있다.

실제로 Error가 발생할 때마다 프로그램이 종료되면 상당히 곤란해지는 경우가 많다.

 

종료시키지 않는 방법이 바로 try catch문을 이용해서 Exception의 흐름을 제어하는 것이다.

 

 

아래의 예제를 통해 설명하겠다.

 

  • try 키워드 뒤에 { . . . } 범위가 있다.
  • catch 키워드 뒤에 { . . .} 범위가 있다.
  • catch는 ArrayIndexOutOfBoundsException을 인자로 받는다.
  • 받은 인자를 통해 printStackTrace메소드를 실행시킨다.

 

try 키워드의 범위안에는 Error가 발생할 것으로 의심되는 코드들을 넣으면 된다.

 

catch 키워드는 발생할 것으로 예상되는 Exception을 인자로 받는다.

이때 인자는 위에서 보았던 Exception 클래스의 하위클래스여야한다.

 

catch 키워드 범위안에 있는 코드들은 만약 catch 키워드가 Exception을 받아오면 실행이 된다.

 

 

이제 실행 결과를 보겠다.

 

실행 결과

어디서 많이 보던 경고 메세지가 보인다. (오류로 인해 프로그램 종료시 보이는 알람)

실제로 프로그램에서도 오류가 발생하면 printStackTrace를 통해 오류 내용을 출력한다.

하지만 밑에 hi를 보면 프로그램은 종료되지 않았고 알람이 출력만 되었다는 것을 알 수 있다.

 

 

try catch문은 이처럼 try와 catch를 통해 실행 되는 것을 알 수 있다. (try와 catch는 한 쌍이 아니다)

 

catch문은 여러개를 사용 할 수 있다.

각각의 Exception 마다 조치를 다르게 해야할 경우 catch문을 여러개 사용할 수 있다.

 

catch문의 인자를 모든 ~Exception 클래스의 부모클래스인 Exception e로 받으면

모든 오류들에 대해 강제종료를 막을 수 있다.

 

여기서 추가적으로 프로그래머가 Exception을 만들 수도 있다.

 

프로그래머의 재량으로 Exception을 통해 어떠한 행위를 제한할 수도 있다.

 

 

아래의 예제를 통해 설명하겠다.

 

CustomException 생성

  • CustomException은 Exception을 상속받고있다.
  • serialVersionUID를 갖고있다.

 

특별한건 없다. 클래스를 정의하고 Exception을 상속한 것 뿐이다.

Exception을 상속했을 때 혹시 클래스 이름에 노란줄이 그어지면 serialVersionUID를 생성해주는게 좋다.

 

이제 CustomException을 사용해 보겠다.

 

throw 키워드를 통해 CustomException 클래스를 생성하고 제어한다.

 

throw 키워드를 통해 Exception 클래스를 던지고,

catch 키워드를 통해 Exception 클래스를 잡아서 인자로 사용한다고 생각하면 편하다.

 

CustomException 사용 예제

  • throw 키워드는 new를 통해서 CustomException 인스턴스를 생성한다.
  • catch 문이 2이고 각각 ArrayIndexOutOfBoundsException과 CustomException을 받는다.

 

추가적으로 이때 throw는 혼자 있을 수 있지만 (if)

catch는 반드시 throw가 있어야 한다. (else)

 

이제 실행 결과를 확인해 보겠다.

 

실행 결과

실행 결과를 통해 알 수 있는 것은

throw 키워드가 실행되면 try문을 탈출한다는 것이다.

그 결과로 ArrayIndexOutOfBoundsException을 받는 catch문은 실행이 되지 않았다는 것을 실행결과를 통해 알 수 있다.

 

보통 CustomException을 만들 때 Exception 대신 RuntimeException을 상속한다.

프로그램 실행중 발생하는 모든 Error는 Runtime Error에 속하기 때문이다.

 

이해를 쉽게 하려고 Exception을 상속한 것이다.

 

그리고 e.printStackTrace()는 Exception의 부모 클래스인 Throwable에 정의되어있다.

그래서 Exception을 상속하기만하면 사용할 수 있는 것이다.

 

또한 메소드에 Throws 키워드를 붙여서 catch를 잠시 미룰 수도 있다.

 

customMethod를 정의할 때 아래와 같이 throws 를 사용하면 된다.

thorws 사용 예제
throws 사용 예제 2

try문 안에서 customMethod 실행중에 CustomException이 발생하면 바로 catch되고 try문을 탈출하게 되는 것이다.

 

마지막으로 사실 finally 키워드가 있다.

 

그냥 try catch문에서 catch문 뒤에 붙는데 에러 발생 결과에 무관하게 finally의 범위 안에 있는 코드들은 무조건 실행된다.