예외처리의 기본 = 로깅. 기록하는 것. 에러가 발생했을 때의 상태를 저장해 분석.
프로그램 오류 = 잘못된 방향으로 흘러가는 것.
컴파일 = 사전 예방
컴파일러가 점점 똑똑해지고 있음. 엄격하게.
.java → 컴파일 → .class
모든 예외의 최고 조상 = Exception
예외 처리하기
try {
// 예외가 발생할 가능성이 있는 문장.
} catch (Exception1 e1){
// 에러 처리
} catch (Exception2 e2){
// 에러 처리
}
- if문임. try-catch 중첩 가능.
- 같은 이름의 참조변수 사용 불가.
JVM이 에러 출력해줌.
예외가 발생하면 예외 객체가 만들어짐.(해당 예외 클래스의 인스턴스)
예외객체 - 예외에 대한 정보를 갖고 있음. 예외 보고서. 예외 정보, 메세지.. 이런걸 예외 객체에 담아서 전달. catch블럭에 선언된 참조 변수로 접근 가능.
하나의 메서드 내에 여러 개의 try-catch문 포함 가능.
try{
...
}catch(ExceptionA | ExecptionB e){. // = if(e instanceof ExceptionA || e instanceof ExecptionB)
e.printStackTrace();
}
합집합 할 때 조상|자손이면 에러남. 조상만 써주는거랑 똑같기 때문.
catch문 ()에서 instanceof연산자로 검사.
해당 결과가 true인 catch블럭을 찾으면 블럭 안 내용을 수행하고 빠져나감.
모든 예외는 Exception의 자손들이기 때문에 catch()안에 Exception 타입의 참조변수를 선언하면 어떤 예외가 발생해도 처리 가능.
//printStackTrace()
java.lang.ArithmeticException: / by zero
at ExceptionEx8.main(ExceptionEx8.java:7)
//getMessage()
/ by zero
try{
...
} catch (ExceptionA | ExceptionB e){
e.printStackTrace();
}
여러 catch블럭을 하나로 합칠 수 있다. 개수 제한 없음.
|로 연결된 예외 클래스들의 공통 분모인 조상 예외 클래스에 선언된 멤버만 사용 가능.
catch블럭 안에서 ExceptionA의 메서드를 사용하려면 if문으로 해당 예외인지 검사하고 형변환 해서 사용해야함.
if (e instanceof ExceptionA){
ExceptionA e1 = (ExceptionA)e;
e1.methodA();
}
throw를 사용해 고의로 예외 발생시킬 수 있음.
Exception e = new Exception(”고의임”);throw e;두줄 합치면 → throw new Exception(”고의로 발생시킴”);
예외를 직접 처리하거나 보고시키기.
예외 처리 안하고 예외 발생시키면 컴파일도 안됨.
→ RuntimeException발생시키면 컴파일은 됨, 실행은 비정상종료.
RuntimeException클래스와 그 자손 클래스들에 해당하는 예외는 프로그래머 실수에 의해 발생하는 것들이기 때문에 예외 처리를 강제하지 않음.
예외 처리 안해줬을 때 예외 발생해서 프로그램 죽을 때 나오는 에러 메세지
→ JVM이 출력함. default 예외 처리기.
실제로 예외를 처리하는 것이 아닌, 해당 메서드를 호출 시 이런 예외가 발생할 수 있으니 이 메서드를 호출하는 쪽에서 예외를 처리해야 한다고 알려주는 것. 떠넘기기.
선언부에 throws를 사용해 예외를 적어주면 됨.
void method() throws Exception1, ... ExceptionN {
//함수 내용
}
throws Exception 하면 모든 예외가 발생할 수 있다는 뜻.
-> 예외를 선언하면 해당 예외의 자손 예외까지도 발생할 수 있다는 뜻임.
보통 RuntimeException클래스들은 안적음. 꼭 처리해줘야 하는 예외만 선언함.
파일 이름 예외.
finally 블럭
예외의 발생여부에 상관없이 실행되어야하는 코드를 포함시킬 목적으로 사용.
try-catch-finally
try {
// 예외가 발생할 가능성이 있는 문장.
} catch (Exception1 e1){
// 에러 처리
} finally {
// 예외의 발생여부에 상관없이 실행되어야하는 문장.
}
try나 catch문안에 return문이 있어도 finally는 실행됨.
class MyExceptioon extends Exception {
//에러코드 추가를 위한 필드 추가
private final int ERR_CODE;
MyException(String msg, int errCode){
super(msg); //조상인 Exception클래스의 생성자 호출.
ERR_CODE = errCode;
}
public int getErrCode(){
return ERR_CODE;
}
}
기존의 예외클래스는 주로 Exception을 상속받아 checked예외로 작성하는 경우가 많았지만 요즘엔 RuntimeException을 상속받아 작성함. checked예외는 무조건 처리해줘야 하기 때문에 코드가 복잡해짐.
예외 처리를 해놓고 다시 던지기.
한 메서드 내에서 발생할 수 있는 예외가 여럿인 경우, 몇 개는 try-catch로 처리. 나머지는 선언부에 지정하여 호출한 메서드에서 처리하도록 하여 양쪽에서 나눠 처리.
→ 예외를 처리한 후에 인위적으로 다시 발생시키는 방법을 통해 가능. (예외 되던지기)
반환값이 있는 return문의 경우, catch블럭에도 return문이 있어야함.
→ 예외가 발생해도 값을 반환해야하기 때문.
catch블럭 안에 비어있어도 그 블럭안에 들어가면 예외처리 된 걸로 봄.
한 예외가 다른 예외를 발생시킬 수 있음.
예외A가 예외B를 발생시켰다면, A를 B의 원인예외라고 함.