KH

[JAVA] 20230223 예외 처리(Exception)

十月 2023. 2. 23. 14:37

IO를 위해.. 미리..

꼭 알아야 할 것은

★ 언체크드 / 체크드 어떻게 구분할 수 있는지

★ 예외 처리 방법 알기


『예외 처리(Exception)』


[프로그램 오류]

프로그램 수행 시 치명적 상황으로 비정상 종료 상황이 발생한 것

 

〈오류 종류〉

1. 컴파일 에러 : 프로그램 실행을 막는 소스 상의 문법 에러 (소스 구문 수정하여 해결) ≫ 빨간 줄!

2. 런타임 에러 : 입력 값이 틀렸거나, 배열의 인덱스 범위를 벗어나거나, 계산식의 오류 등.

 (수행되고 있다가 잘못 입력해서 나는 오류 / 주로 if문을 사용해 조건으로 에러 처리)

3. 시스템 에러 : 컴퓨터 자체의 오작동으로 인한 에러

 

〈오류 해결 방법〉

:: 소스를 수정해서 해결 가능한 에러를 예외(Exception)이라 함

≫ 예외처리를 통해 해결 (예외 상황'예측 가능한 에러' 구문을 처리하는 방법)

 

 


[예외 클래스 계층 구조]

 

모든 클래스 최고 조상은 Object ,

(Exception과 Error 클래스 모두 Object 클래스 자손)

오류에 대한 최고 조상은 Throwable ,

예외에 대한 최고 조상은 Exception! (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 해결 방법!

 

 

chooseFirst()에서 예외 발생 - chooseFirst()를 호출한 play()로 위임 - … ~

〈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)

 

≫ 사용자 정의 예외 클래스에서는 기본 생성자와 매개변수 생성자 두 개만 있으면 됨