고래씌
[JAVA] 12-1. 예외처리(UncheckedException, CheckedException) 본문
1. 예외처리
▶ 에러(오류) 종류
- 시스템 에러 : 컴퓨터의 오작동으로 인해 발생하는 에러 => 소스코드로 해결이 불가능(심각한 에러)
- 컴파일 에러 : 소스코드상의 문법적인 문제로 발생하는 에러 => 소스코드의 수정으로 해결가능(빨간밑줄로 알려줌)
- 런타임 에러 : 소스코드상으로는 문제가 없는데, 프로그램을 실행 중 발생하는 에러
=> 사용자가 잘못 입력한 경우일수도, 개발자가 예측가능한 경우를 제대로 처리해놓지 않은 걸수도 있다.
- 논리에러 : 소스코드상의 문법적인 문제도 없고, 실행했을때도 에러가 발생하지 않지만, 프로그램의 의도상의 기능과 맞지 않는 경우
▶ 시스템 에러를 제외한 컴파일 에러, 런타임 에러, 논리 에러와 같은 비교적 덜 심각한 것들을 가지고 작업할 예정.
이러한 에러들을 "예외"라고 정의함(Exception)
▶ 예외처리를 해야하는 이유 : 예외 발생시 프로그램이 비정상적으로 종료되는 것을 막고자하기 위함.
▶ 예외처리 방법
① try ~ catch 문을 이용
② throws를 이용(떠넘기기)
2. UncheckedException (반드시 예외처리를 안해도 되는 예외들)
: 프로그램 실행시 발생되는 예외들
▶ RuntimeException의 자식클래스들
- ArrayIndexOutOfBoundsException : 배열의 부적절한 인덱스로 접근할 때 발생하는 예외
- NegativeArraySizeException : 배열의 크기를 음수로 지정할 경우 발생하는 예외
- ClassCastException : 허용할 수 없는 형변환이 진행될 경우 발생하는 예외
ex) Object ob = new String("d"); → ((Integer)ob) 형변환 불가.
- NullPointerException : 참조변수가 null 값을 저장함에도 불구하고, 특정 필드 및 메소드에 접근하려고
할 때 발생한다.(null값 저장은 아무 문제 없다)
- ArithmeticException : 나누기 연산시 0으로 나눌때 발생하는 예외
- ....
☞ 이러한 RuntimeException과 관련한 예외들은 예외상황이 충분히 예측 가능한 상황이기 때문에 예외자체가 발생하지 안되게끔 조건문으로 해결 가능하긴함. 굳이 예외처리를 할 필요가 없다.
1) ArithmeticException
: 나누기 연산시 0으로 나누고자할 때 발생하는 예외
■ 사용자에게 두개의 정수값을 입력받아 나눗셈 연산 결과 출력
package com.kh.exception.controller;
import java.util.Scanner;
public class A_UncheckedException {
private Scanner sc = new Scanner(System.in);
public void method1() {
// ArithmeticExcepton : 나누기 연산시 0으로 나누고자할 때 발생하는 예외
// 사용자에게 두개의 정수값을 입력받아 나눗셈 연산 결과 출력
System.out.print("첫번째 정수 : ");
int num1 = sc.nextInt();
System.out.print("두번째 정수(0 제외) : ");
int num2 = sc.nextInt();
sc.nextLine();
}
■ 해결방법 1.
조건문으로 처리(애초에 예외 자체가 발생되지 않게끔 if문으로 조건검사 후 계산 진행)
package com.kh.exception.controller;
import java.util.Scanner;
public class A_UncheckedException {
private Scanner sc = new Scanner(System.in);
public void method1() {
// ArithmeticExcepton : 나누기 연산시 0으로 나누고자할 때 발생하는 예외
// 사용자에게 두개의 정수값을 입력받아 나눗셈 연산 결과 출력
System.out.print("첫번째 정수 : ");
int num1 = sc.nextInt();
System.out.print("두번째 정수(0 제외) : ");
int num2 = sc.nextInt();
sc.nextLine();
// 해결방법 1. 조건문으로 처리(애초에 예외 자체가 발생되지 않게끔 if문으로 조건검사 후 계산 진행)
if(num2 == 0) {
System.out.println("0으로 나눌 수 없습니다.");
}else {
System.out.println("나눗셈 연산 결과 : " + (num1 / num2));
}
System.out.println("프로그램 종료");
}
}
■ 해결방법 2.
예외처리 구문으로 해결(예외가 발생했을 경우를 대비해서 실행할 내용을 정의해두는 것)
try ~ catch문
[표현법]
try {
예외가 발생될수도 있는 소스코드가 존재하는 구문
} catch (발생될 예외클래스 변수명){
e.printStackTrace(); // 오류를 추적할 수 있음. 현재 예외가 발생한 정보를 볼 수 있다.
해당 예외가 발생할 경우 실행할 구문
}
package com.kh.exception.controller;
import java.util.Scanner;
public class A_UncheckedException {
private Scanner sc = new Scanner(System.in);
public void method1() {
// ArithmeticExcepton : 나누기 연산시 0으로 나누고자할 때 발생하는 예외
// 사용자에게 두개의 정수값을 입력받아 나눗셈 연산 결과 출력
System.out.print("첫번째 정수 : ");
int num1 = sc.nextInt();
System.out.print("두번째 정수(0 제외) : ");
int num2 = sc.nextInt();
sc.nextLine();
// 해결방법 2. 예외처리 구문으로 해결(예외가 발생했을 경우를 대비해서 실행할 내용을 정의해두는 것)
/*
* try ~ catch문
* [표현법]
* try {
* 예외가 발생될수도 있는 소스코드가 존재하는 구문
* } catch (발생될 예외클래스 변수명){
* 해당 예외가 발생할 경우 실행할 구문
* }
*/
try {
System.out.println("나눗셈 연산 결과 : " + (num1 / num2));
}catch(ArithmeticException e) {
e.printStackTrace(); // 오류를 추적할 수 있음. 현재 예외가 발생한 정보를 볼 수 있다.
System.out.println("0으로 나눌 수 없습니다.");
}
System.out.println("프로그램을 종료합니다.");
}
}
2) cath블럭이 여러개 있는 경우
■ try ~ catch 문을 사용하는데 catch블럭이 여러개 있는 경우
public void method2() {
System.out.print("정수입력(0 제외 ) : ");
try {
int num = sc.nextInt(); // InputMismatchException
System.out.println("나눗셈 연산 결과 : " + (10/num)); // AritmeticException 발생가능한 코드
}catch(ArithmeticException e) {
System.out.println("0으로 나눌 수 없습니다.");
}catch(InputMismatchException e) {
System.out.println("정수값을 입력해주세요.");
}// 다중 catch블럭. : 예외가 여러개 발생할 가능성이 있을 경우 사용
System.out.println("프로그램 종료");
}
3) 범위가 작은 자식타입의 예외를 먼저 기술!
▶ RuntimeException 관련된 예외는 대부분
- 조건문으로 해결 가능 => 예외 자체가 발생 안되게끔 개발자가 소스코드로 핸들링 하는 것(예외처리x)
- 예외 처리 구문으로 해결 가능 => 예외가 발생했을 때를 대비해서 그때 실행할 내용을 정의해두는 것
- 예측이 가능한 상황 → 조건문으로 해결가능(권장)
- 예측이 불가능한 상황 → 예외처리 구문으로 해결
▶ RuntimException 계열은 충분히 예측 가능한 상황이기 때문에 조건문으로 해결하는 것을 권장
필수는 아니다 => UncheckedException
- RuntimeException 은 부모타입의 예외 클래스!
- ArrayIndexOutOfBoundsException은 자식타입의 예외 클래스
★ 범위가 작은 자식타입의 예외를 먼저 기술해야한다!! ★
public void method3() {
// ArrayIndexOutOfBoundsException :
// NegativeArraySizeException :
System.out.print("배열의 크기 : ");
try {
int size = sc.nextInt();
if(size < 0) {
System.out.println("음수로 제시할 수 없습니다.");
return;
}
int[] arr = new int[size];
if(arr.length > 100)
System.out.println("100번째 인덱스 값 : " + arr[100]);
}catch(ArrayIndexOutOfBoundsException e) { // 범위가 작은 자식타입의 예외를 먼저 기술해야한다.
System.out.println("부적절한 인덱스로 접근했다.");
// 다중 catch블럭과 비교했을 때 코드블럭이 줄어들긴 했지만 정확히 어떤 예외가 발생했는지 알 수 없음
}catch(RuntimeException e) { // 다형성을 적용하여 부모타입의 예외클래스 하나만 작성
System.out.println("에러가 발생하긴 했는데, 입력값이 잘못 입력되었을 수도 있고, "
+ "배열의 크기를 음수로 입력했을 수도 있고,"
+ "부적절한 인덱스로 접근했을수도 있다.");
}
// catch(ArrayIndexOutOfBoundsException e) {
// System.out.println("부적절한 인덱스로 접근했습니다.");
// }catch(NegativeArraySizeException e) {
// System.out.println("배열의 크기를 음수로 제시할 수 없습니다.");
// }
}
3. CheckedException (반드시 예외처리를 해줘야 하는 예외들)
(즉, 예측이 불가능한 곳에서 예외가 발생하기 때문에 미리 예외처리구문을 작성해야함)
=> 주로 외부매체외 입출력시 발생
① try ~ catch 문으로 예외처리하기
package com.kh.exception.controller;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class B_CheckedException {
/*
* CheckedException 은 반드시 예외처리를 해줘야하는 예외들
* (즉, 예측이 불가능한 곳에서 예외가 발생하기 때문에 미리 예외처리구문을 작성해야함)
* => 주로 외부매체외 입출력시 발생
*/
public void method2() {
// Scanner와 같이 키보드로 값을 입력받을 수 있는 객체
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("아무 문자열이나 입력해주세요. ");
// 1. try ~ catch으로 예외 처리하기
try {
// 이 메소드 호출시 IOException가 발생할 수도 있음을 컴파일 에러로 알려준다.
String str = br.readLine(); // 문자열값 얻어오는 메소드
}catch (IOException e) {
e.printStackTrace();
}
}
}
② throws 이용해서 예외처리하기 - 별로 추천하지 않는 방법
: 지금 현재 메소드에서 예외를 처리하지 않고, 현재 메소드를 호출한 곳으로 떠넘기는 방법
package com.kh.exception.run;
import java.io.IOException;
import java.util.Calendar;
import com.kh.exception.controller.A_UncheckedException;
import com.kh.exception.controller.B_CheckedException;
public class Run {
public static void main(String[] args) throws IOException {
B_CheckedException bce = new B_CheckedException();
bce.method1();
}
}
package com.kh.exception.controller;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class B_CheckedException {
public void method1() throws IOException {
method2();
}
public void method2() throws IOException {
// Scanner와 같이 키보드로 값을 입력받을 수 있는 객체
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("아무 문자열이나 입력해주세요. ");
// 2. throws : 지금 현재 메소드에서 예외를 처리하지 않고, 현재 메소드를 호출한 곳으로 떠넘기는 방법
String str = br.readLine();
System.out.println("문자열의 길이 : " + str.length());
}
}
※ 정리
예외 발생 시점 | 예외 처리 | |
RuntimeException | 프로그램 실행하는 도중 에러 발생 | 필수 X => UncheckedException |
IOException 그 외 | 컴파일 에러 | 필수 => CheckedException |
'JAVA > JAVA 기초' 카테고리의 다른 글
[JAVA] 13-1. 입출력(IO) (File 클래스 ①) (0) | 2023.10.20 |
---|---|
[JAVA] 예외처리 실습문제 (0) | 2023.10.20 |
[JAVA] 날짜 계산 API 문제 (0) | 2023.10.20 |
[JAVA] 11-4. 기본 API(4) (날짜 클래스) (0) | 2023.10.19 |
[JAVA] 11-3. 기본 API(3) 형변환 클래스(Wrapper 클래스) (0) | 2023.10.19 |