[JAVA] 20230223 예외 처리(Exception)
IO를 위해.. 미리..
꼭 알아야 할 것은
★ 언체크드 / 체크드 어떻게 구분할 수 있는지
★ 예외 처리 방법 알기
『예외 처리(Exception)』
[프로그램 오류]
프로그램 수행 시 치명적 상황으로 비정상 종료 상황이 발생한 것
〈오류 종류〉
1. 컴파일 에러 : 프로그램 실행을 막는 소스 상의 문법 에러 (소스 구문 수정하여 해결) ≫ 빨간 줄!
2. 런타임 에러 : 입력 값이 틀렸거나, 배열의 인덱스 범위를 벗어나거나, 계산식의 오류 등.
(수행되고 있다가 잘못 입력해서 나는 오류 / 주로 if문을 사용해 조건으로 에러 처리)
3. 시스템 에러 : 컴퓨터 자체의 오작동으로 인한 에러
〈오류 해결 방법〉
:: 소스를 수정해서 해결 가능한 에러를 예외(Exception)이라 함
≫ 예외처리를 통해 해결 (예외 상황'예측 가능한 에러' 구문을 처리하는 방법)
[예외 클래스 계층 구조]
모든 클래스 최고 조상은 Object ,
(Exception과 Error 클래스 모두 Object 클래스 자손)
오류에 대한 최고 조상은 Throwable ,
예외에 대한 최고 조상은 Exception! (Exception은 클래스)
≫ 반드시 예외 처리를 해야 하는 Checked Exception와 (안 하면 빨간줄)
예외 처리 안 해줘도 되는 Unchecked Exception으로 나뉨 (문제 생기지 않음)
[예외처리(Exception)]
〈RuntimeException 클래스〉
Unchecked Exception 으로 예외 처리 안 해도 됨
예외 처리보다 코드를 수정하는 경우가 많음 (부주의로 인한 오류)
(RuntimeException 후손이 아니면 무조건 예외 처리를 해 줘야 함)
1 ) ArithmeticException
- 0으로 나누는 경우 발생
- if문으로 나누는 수가 0인지 검사
2) ArrayIndexOutOfBoundsException
- 배열의 범위를 넘어서 참조하는 경우
- 배열명.length를 사용해 범위 체크해야 함
3) NegativeArraySizeException
- 배열 크기를 음수로 지정한 경우 (공간은 음수로 만들 수 없음)
- 배열 크기를 0보다 크게 지정해야 함
4) ClassCastException
- Cast연산자 사용 시 타입 오류
- instanceof연산자로 객체 타입 확인 후 Cast연산
5) NullPointerException
- Null인 참조 변수로 객체 멤버 참조 시도 시 발생
- 객체 사용 전에 참조 변수가 null인지 확인
〈Exception 확인하기〉
[예외처리 방법]
꼭 예외처리를 해야 하는 checked Exception 해결 방법!
〈1. Exception 처리를 호출한 메소드에게 위임하는 법 (like.. 책임 전가)〉
// 메소드 선언 시 throws ExceptionName문을 추가
- 나를 호출한 상위 메소드에게 처리 위임 ≫ 계속 위임하면 main() 메소드까지 위임하게 됨
(나를 호출한 메소드에게 돌아간다 = return의 의미)
- 거기서도 처리되지 않을 경우에는 비정상 종료됨
〈2. Exception 발생한 곳을 직접 처리하는 법〉
// try~catch문을 이용해 예외 처리
- try : exception 발생 가능성이 있는 코드를 안에 기술
(예외가 발생할 법 하다 싶은 코드를 try안에 집어 넣음)
- catch : try 구문에서 exception 발생 시 해당 exception에 대한 처리 기술
내가 쓰고 싶은 만큼 여러 개 exception 처리가 가능 (exception 간의 상속 고려 必)
(try에서 발생한 exception을 안에 집어 넣음)
- finally : exception 발생 여부와 상관 없이 무조건 수행해야 할 로직 기술
중간에 return문을 만나도 finally 구문 실행 / System.exit(); 만나면 무조건 종료
▼ 해 보기
- 결과를 보고 메인 메소드 위에 메소드가 쌓이는 과정과
다시 메인 메소드로 돌아오는 과정을 이해하면 된다!!!!
Stack 구조
- 먼저 넣은 건 제일 나중에 꺼내는 구조
(선입후출 = FILO = First IN Last Out)
▼
1-1) throws (↔ throw는 예외를 억지로 발생시킴)
예외처리를 위임시키는 throws와 혼동하지 말자 ★
≫ method3() 안에 throw를 사용해 예외를 강제로 발생시켰음
하지만 필요 목적에 의해 throw로 예외를 강제 발생시켰다면
웬만해서 ry~catch로 잡지 않는 것이 좋곘다.
≫ method2()로 예외 처리를 위임함
≫ method2()에서 method1()로, method1()에서 main()까지 위임을 해 보았다
throw 하는 동안 직접적인 해결을 하지 않았기 때문에
결론적으로 완전하게 해결되는 방법은 아닌 게 되겠다. (임시방편임)
1-2) try~catch로 1-1에서 발생시킨 예외 처리하기
≫ 실행은 이제 잘 되고, e.printStackTrace(); 가 어떤 에러를 잡았는지 알려줌 (빨간 문장)
2) try~catch 직접 써 보기
≫ 강제로 throw 해 발생시킨 IOExeption을 throws 하여 method2()에서 try~catch를 해 보았다
≫ 만약 System.out.println("예외 잡았다!"); 를 적은 것이 아니라
e.printStackTrace();를 했다면 빨간 글씨로 어떠한 에러를 잡았는지 나오게 된다.
≫ 생성자에 매개변수를 입력해서 메세지를 받아줄 수 있다
3) finally
≫ finally는 예외와 상관 없이 무조건 수행되는 것을 볼 수 있다
IOException은 ZipException의 부모 타입
≫ 나보다 부모인 타입이 위에 있으면 아래 자식 타입이 받을 수 없어
아래로 내려갈수록 부모 타입을 기술해주어야 한다 (다형성 개념으로 인해)
(catch를 쓸 때는 부모 자식 관계 (상속 관계)를 꼭 고려해야 한다.)
"옳은 배치 순서"는?
① ZipException
↓
② IOException
↓
③ Exception
≫ Exception 클래스는 예외의 가장 조상이기 때문에
맨 위에 위치하면 아래 있는 catch절이 들어올 수가 없다.
따라서 가장 부모일수록 가장 밑으로 내려가야 한다
▼
[Exception과 오버라이딩]
// 부모 메소드의 예외 처리 클래스 범위 보다 좀은 범위로 예외처리 수정 가능
≫ 부모보다 좁은 범위는 되지만 넓은 범위는 안 된다
[사용자 정의 예외]
Exception 클래스를 상속 받아 예외 클래스를 작성
Exception 발생하는 곳에서 throw new 예외클래스명() (import 해야 함)
1)
≫ 이름이 Exception이라고 예외 클래스가 되는 것이 절대 아님!
extends Exception 해서 상속 받았기 때문에 예외 클래스가 됨
2)
3)
▼
≫ 사용자 정의 예외 클래스에서는 기본 생성자와 매개변수 생성자 두 개만 있으면 됨