try-catch를 사용할 때 주의해야하는 점은 변수의 선언 위치이다.
try 블록 내에서 선언한 변수는 catch에서는 접근을 할 수가 없음.
따라서 선언을 try-catch 문 밖에서 해주자. null로 초기화하여 선언한 뒤, try에서 값을 할당하는 것은 괜찮다. 예외가 발생하기 전 코드까지는 실행이 되기 때문이다.
try-catch 문에서 마지막에 반드시 실행되는 블록. 코드의 중복을 막기 위해서 반드시 필요하다. (여러 개의 catch가 있는 경우)
원래 catch 블록이 시작되기 전에 있는 소괄호 안에는 예외의 종류를 명시해야한다.
예를 들어 NullPointerException을 먼저 검사하고 이후에 ArrayIndexOutOfBoundsException을 검사하기
(널인 객체로 작업하면 안되니까 NullPointerException을 먼저 검사해준 것이다.)
catch문을 사용할 때에는 Exception 클래스로 catch하는 것을 가장 아래에 추가하자. 예상치 못한 예외가 터지게 되면 처리하기 어렵기 때문이다.
모든 예외의 부모는 java.lang.Exception 클래스이다.
부모 Exception 클래스가 이미 예외를 캐치하면 밑에 자식 Exception 클래스가 예외를 캐치할 기회가 없음. 즉 필요없는 catch 블록이 만들어져있는 상황인 것이고 이런 경우 컴파일이 되지 않는다.
Exception은 세 가지로 나눌 수 있다.
error와 runtime exception을 제외한 예외들이 checked exception이다.
에러는 프로그램 밖에서 발생한 문제이다. 예를 들어 서버의 디스크가 고장 나거나 하는 상황이다.
Error로 끝나는 문제와 Exception으로 끝나는 문제의 차이점은
런타임 예외는 예외가 발생할 것을 미리 감지하지 못했을 때 발생한다. (컴파일시에 체크되지 않음. 예를 들면 NullPointerException)
이 runtime exception의 예외들은 모두 RuntimeException 클래스를 상속받은 것들이다.
Exception과 Error의 공통 부모 클래스는 Throwable 클래스이다. (Throwable 클래스 또한 Object 클래스를 상속 받는다.)
Throwable 클래스에 선언되어있고, Exception에서 Override하는 메소드는 10개가 넘는다. 그 중 가장 많이 쓰이는 3가지는 다음과 같다.
예외가 항상 발생하지 않고, 실행시에 발생할 확률이 매우 높은 경우 런타임 예외로 만드는 것이 나을 수 있다.
즉, 예외 클래스 선언시 'extends Exception'이 아닌, 'extends RuntimeException'으로 선언하는 것이다.
이렇게 선언하면 이 예외를 throw하는 메소드를 사용할 때 try-catch로 묶지 않아도 컴파일 에러가 발생하지 않는다.
결론: 일반적으로 실행시 예외를 처리할 수 있는 경우에는 RuntimeException 클래스를 확장하는 것이 권장된다.