예외 (Exception)
ex) try-catch
public static void main(String [] args){
int [] intArray = new int [5];
try {
// 예외가 발생하는 문장들을 묶어준다.
System.out.println(intArray[10]);
} catch (Exception e) {
// 예외가 발생했을 때 처리해주는 문장
}
}
- 우리가 예상한 / 예상치 못한 일이 발생하는 것을 미리 예견하고 안전장치를 하는 것
- ex) null 인 객체에 메소드를 호출
파일을 읽으려고 했는데 파일이 존재하지 않는 경우 .... - 예외 발생 시 예외가 발생한 클래스와 메소드 이름, 줄의 번호를 출력해준다.
try-catch 블록
- try - catch 블록은 예외를 처리하는 역할을 한다.
- 예외가 발생하는 문장들을 try { } 중괄호 안에 묶어준다.
- 예외가 발생했을 때 처리를 해주는 문장을 catch( ){ } 중괄호 안에 묶어준다.
- try 블록 안에서 예외가 발생 시 그 이후 코드들은 수행되지 않고 catch 블록으로 넘어간다.
- try 블록 내 예외가 발생하지 않는 경우
- try 블록 내 모든 코드가 실행되고 catch 블록 내 코드는 실행되지 않으며 try - catch 문장 이후 내용이 실행된다.
- try 블록 내 예외가 발생한 경우
- try 블록에서 예외가 발생한 이후 코드는 실행되지 않으며 catch 블록 내 코드는 반드시 실행되고 try - catch 문장 이후 내용이 실행된다.
- try 블록 내 예외가 발생하지 않는 경우
- System.err.println()
- 일반적인 콘솔 화면에서는 별로 구분이 안되지만, IDE에서는 출력 결과가 다른색으로 표시된다.
- 오류가 발생하는 부분에 System.err 사용을 생활화 하는 것이 좋다.
- try-catch에서 하기 쉬운 실수
- try는 {}로 쌓여있기에 try 블록 내에서 선언한 변수를 catch 블록 내에서 사용할 수 없다.
- catch 블록에서 사용할 변수는 try 블록 전에 미리 선언해놓아야 한다.
finally 블록
- try-catch 구문에 추가로 붙을 수 있는 블록
- 예외를 처리할 때 finally는 "어떠한 경우에도 반드시 실행한다."의 의미를 가지고 있다.
- 예외 발생 여부와 상관없이 finally 블록은 무조건 실행된다.
- finally 블록은 코드의 중복을 피하기 위해서 반드시 필요하다.
catch 블록
- catch ( ) 소괄호 안에는 예외의 종류를 명시한다.
- try는 한 번에 여러 catch 블록을 사용해도 된다.
- try 블록에서 예외 발생 시 그 예외와 관련있는 catch 블록을 찾아서 실행한다.
- catch 블록은 순서를 따지기 때문에 순서가 매우 중요하다.
- 모든 예외의 부모 클래스는 java.lang.Exception 클래스
- 예외 처리 순서가 부모 클래스가 먼저인 경우 자식 클래스는 예외 처리 기회가 없다.
- 이런 경우 컴파일 에러가 발생한다.
- catch 문 사용 시 Exception 클래스를 사용하는 문장은 가장 아래에 추가하는 것이 좋다.
- 예상치도 못한 예외가 발생하면 제대로 처리가 되지 않기 때문
- catch 블록에 Exception 클래스가 없는 경우 발생한 예외와 관련있는 블록이 없으면 예외가 발생하며 쓰레드가 종료된다.
- 그렇기에 가장 마지막에 Exception 클래스로 catch 블록을 선언하여 예외들이 빠져나가지 못하게 하는 것이 좋다.
예외의 종류
- checked exception / error / runtime exception (unchecked exception)으로 총 세가지가 있다.
- error와 unchecked exception이 아닌 모든 예외는 checked exception이다.
에러 (Error)
- 자바 프로그램 밖에서 발생한 예외
- ex) 서버의 디스크 고장 / 메인보드 고장으로 인한 자바 프로그램 비정상 동작....
- Exception 클래스는 에러가 아니다.
- 오류의 이름이 Error로 끝나면 에러, Exception으로 끝나면 예외
- Error와 Exception의 차이점
- 프로그램 안과 밖 어디서 발생했는지의 여부
- 프로그램이 멈춰버리는지 계속 실행할 수 있는지의 여부
- Error는 프로세스에 영향을 준다.
- Exception은 쓰레드에만 영향을 준다.
런타임 예외 (Runtime Exception)
- 예외가 발생할 것을 미리 감지하지 못했을 때 발생한다.
- 런타임 예외에 해당하는 모든 예외는 RuntimeException을 확장한 예외들이다.
- 예외를 묶어주지 않는다고해서 컴파일할 때 예외가 발생하지는 않지만 실행시에 발생할 가능성이 있는 예외들.
- 컴파일 시 체크를 하지 않았기에 unchecked exception이라고 불리기도 한다.
Throwable 클래스
- java.lang 패키지에 선언되어 있으며 Exception과 Error 클래스의 공통 부모 클래스다.
- 성격은 서로 달라도 모두 동일한 이름의 메소드를 사용해 처리할 수 있도록 하기 위한 상속 관계.
- Exception / Error를 처리할 때 Throwable 클래스를 상속받아 처리하도록 되어 있기에 Throwable로 처리해도 무관하다.
- Throwable 생성자 종류
- 디폴트 생성자
- 예외 메시지를 String으로 넘겨주는 생성자
- 예외의 원인을 객체로 넘겨주는 생성자
- 예외 메시지와 원인을 객체로 함께 넘겨주는 생성자
- Throwable 클래스의 메소드
- getMessage() : 예외 메시지를 String 형태로 받는다. 어떤 예외가 발생되었는지 확인시 유용하다.
메시지를 활용해 별도의 예외 메시지를 사용자에게 보여줄 때 좋다. - toString() : 예외 메시지를 String 형태로 받는다. getMessage() 보다는 더 자세하게, 예외 클래스 이름도 함께 제공한다.
- printStackTrace() : 첫 줄에 예외 메시지를 출력, 두 번째 줄부터 예외가 발생하게 된 메소드들의 호출 관계(스택 트레이스)를 출력한다.
- getMessage() : 예외 메시지를 String 형태로 받는다. 어떤 예외가 발생되었는지 확인시 유용하다.
Throw / Throws
public class ThrowSample {
public static void main(String[] args) {
ThrowSample ts = new ThrowSample();
ts.throwException(13);
}
public void throwException(int num) {
try {
if (num > 12) {
// throw 시 해당하는 예외가 없으면 메소드 밖으로 던진다.
throw new Exception("Number is over than 12");
}
System.out.println("number is" + num);
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 예외를 발생시키는 방법
- try 블록 내에서 throw라고 명시한 후 예외 클래스의 객체를 생성하거나 생성된 객체를 명시한다.
- throw 문장 이후에 있는 모든 try 블록 내 문장들은 수행되지 않고 catch 블록으로 이동한다.
- catch 블록 중 throw 한 예외와 동일하거나 상속 관계에 있는 예외가 있다면 그 블록에서 예외를 처리할 수 있다.
- throw 한 예외 클래스가 catch 블록에 선언되어 있지 않거나 throws 선언에 포함되어 있지 않으면 컴파일 에러 발생.
- 예외를 throw하는 이유
- 해당 메소드에서 예외를 처리하지 못하는 상황
- 미처 처리하지 못한 예외가 있을 경우에 대비
public class ThrowSample {
public static void main(String[] args) {
ThrowSample ts = new ThrowSample();
try {
ts.throwException(13);
} catch (Exception e) {
e.printStackTrace();
}
}
// 해당 메소드에 throws로 선언하면 예외가 발생했을 때 try-catch로 묶지 않아도 괜찮다.
// 호출한 메소드로 예외 처리를 위임하는 것이기에 호출한 메소드에 try-catch를 사용해줘야 한다.
public void throwException(int num) throws Exception {
if (num > 12) {
throw new Exception("Number is over than 12");
}
System.out.println("number is" + num);
}
}
- 만약 해당하는 예외가 없다면 발생된 예외는 메소드 밖으로 던져버린다.
- 예외가 발생된 메소드를 호출한 메소드로 던진다는 의미로 이럴 때 필요한 것이 throws 구문이다.
- 메소드 선언 시 매개 변수 소괄호 뒤 throws 키워드와 던질 예외 종류를 명시함으로 예외를 선언
- 해당 메소드에서 선언한 예외가 발생 시 호출한 메소드로 예외가 전달된다.
- 만약 두 가지 이상의 예외를 던질 경우 ,(콤마)로 구분해 예외 클래스 이름을 적어준다.
- 메소드 선언 시 throws 구문으로 하는 경우
- 예외가 발생했을 때 try-catch로 묶지 않아도 메소드를 호출한 메소드로 예외 처리를 위임하기에 문제가 되지 않는다.
- 하지만 throws로 선언된 메소드를 호출한 메소드에서는 반드시 try-catch로 호출한 부분을 묶어줘야 한다.
- 호출한 메소드를 try-catch로 묶지 않으려면 그 메소드를 호출한 메소드를 다시 throws 하는 방식도 있다.
- throws 한 것을 다시 thorws 하는 것은 좋지 않은 방법이다.
- 가장 좋은 방법은 throws 하는 메소드를 호출하는 메소드에서 try-catch로 처리하는 방법.
- 묶어주지 않으면 컴파일 에러 발생
- 호출한 메소드를 try-catch로 묶지 않으려면 그 메소드를 호출한 메소드를 다시 throws 하는 방식도 있다.
- catch 블록에서 예외를 throw 할 때도 메소드 선언의 throws 구문에 해당 예외가 정의되어 있어야 한다.
예외 클래스 작성
- Error와 관련된 클래스는 개발자가 손댈 필요도, 대서도 안된다.
- Exception을 처리하는 예외 클래스는 개발자가 임의로 추가해서 만들 수 있다.
- Throwable 클래스를 상속 받아도 되지만, java.lang.Exception 클래스를 상속 받는 것이 좋다.
- 예외 클래스가 되기 위한 조건은 예외 관련 클래스를 확장하는 것이다.
- 예외 클래스를 임의로 만들 때 반드시 Throwable의 직계 클래스들(Throwable 클래스, Exception 클래스...)을 상속 받아 만들어야 한다.
- 예외 클래스를 만들어 예외를 던지고 catch 블록에서 사용하는 경우 무조건 만든 예외 클래스로 catch 해야만 하는 것이 아닌 부모 클래스인 Exception으로 catch해도 무방하다.
예외 처리 전략
- 예외 처리를 할 때 표준을 잡고 진행하는 것이 좋다.
- 예외를 직접 만드는 경우 Exception 클래스를 확장하는 것보다 RuntimeException 클래스를 확장하는 것이 더 나은 경우도 있다.
- 반드시 try-catch로 묶어줘야 하는 경우에만 Exception 클래스를 상속받는다.
- Exception 상속 시 무조건 예외를 던지는 해당 메소드에 try-catch로 묶어줘야 한다,
- 일반적으로 실행 시 예외를 처리할 수 있는 경우, 예외가 항상 발생하지 않고 실행 시에 발생할 확률 이 높은 경우에는 RuntimeException 클래스를 상속 받는 것이 더 좋다.
- 이런 경우 해당 예외를 던지는 throw 메소드를 사용하더라도 try-catch로 묶지 않아도 컴파일 에러가 발생하지 않는다.
- 하지만 예외가 발생할 확률은 높으므로 호출하는 메소드를 try-catch로 묶어주는 것이 좋다.
- 반드시 try-catch로 묶어줘야 하는 경우에만 Exception 클래스를 상속받는다.
- catch 문에서 아무런 작업 없이 공백을 놔두면 예외 분석이 어려워지므로 하지마라.
- catch 문에서 아무런 작업을 하지 않으면 문제가 어디서 발생했는지 찾지 못한다.
- 개발 표준을 잡을 때 catch 문에서 어떻게 처리할지를 명시적으로 선언해둬야한다.
- catch 문에서 로그를 남기는 등의 작업을 하고 예외를 throw 함으로 문제가 발생한 정확한 원인을 찾을 수 있다.
간단 내용 정리
1. 예외를 처리하기 위한 세가지 블록에는 어떤 것이 있나요?
ㅡ> try - catch - finally
2. 첫번째 문제의 답 중에서 "여기에서 예외가 발생할 것이니 조심하세요"라고 선언하는 블록은 어떤 블록인가요?
ㅡ> try, 예외가 발생할 수 있는 부분을 묶는다.
3. 첫번째 문제의 답 중에서 "예외가 발생하던 안하던 얘는 반드시 실행되어야 됩니다."라는 블록은 어떤 블록인가요?
ㅡ> finally, 예외 발생 여부와 상관없이 무조건 실행하도록 한다.
4. 예외의 종류 세가지는 각각 무엇인가요?
ㅡ> Checked Exception, Error, Unchecked Exception (Runtime Exception)
5. 프로세스에 치명적인 영향을 주는 문제가 발생한 것을 무엇이라고 하나요?
ㅡ> error, 자바 프로그램 밖에서 생기는 문제에 관한 것
6. try나 catch 블록 내에서 예외를 발생시키는 예약어는 무엇인가요?
ㅡ> throw, 예외를 발생시키면 해당 메소드를 호출한 메소드로 예외를 던진다.
7. 메소드 선언시 어떤 예외를 던질 수도 있다고 선언할 때 사용하는 키워드는 무엇인가요?
ㅡ> throws, 메소드 선언 시 던질 예외 종류를 명시한다.
8. 직접 예외를 만들 때 어떤 클래스의 상속을 받아서 만들어야만 하나요?
ㅡ> java.lang.Exception이나 RuntimeException 클래스
Exception을 상속 받으면 무조건 예외를 던지는 해당 메소드에서 try-catch로 묶어야한다는 단점이 존재
따라서 RuntimeException 클래스를 상속 받는 것이 좋다.
출처: 이상민, <자바의 신 VOL.1> 로드북
'Java > 자바의 신 VOL.1' 카테고리의 다른 글
16. 클래스 안에 클래스가 들어갈 수도 있구나 (0) | 2024.06.25 |
---|---|
15. String (0) | 2024.06.25 |
13. 인터페이스와 추상 클래스, enum (1) | 2024.06.22 |
12. 모든 클래스의 부모 클래스는 Object에요 (0) | 2024.06.21 |
11. 매번 만들기 귀찮은데 누가 만들어 놓은 거 쓸 수 없나요? (0) | 2024.06.21 |