에러종류
- 시스템에러 : 컴퓨터의 오작동으로 발생하는 에러 => 스스로 해결 안됨 => 심각한 에러
- 컴파일에러 : 소스코드 문법상 오류 => 빨간줄로 애포에 오류로 알려줌 (개발자의 실수)
- 런타임에러 : 코드 상으로는 문제가 없는데 프로그램 실행중에 발생하는 에러 (사용자의 실수일 수도 있고 개발자의 실수일 수도 있다.(예외처리))
- 논리에러 : 문법적으로 문제없고 실행했을 때도 굳이 문제는 없지만 프로그램 의도상 맞지않는 것
시스템 에러를 제외한 컴파일 에러, 런타임 에러, 논리 에러와 같은 비교적 덜 심각한 것
이런것들을 "예외" 라고함!!! => Exception
이런 "예외"가 "발생"했을 경우에 대해서 "처리"하는 방법을 "예외처리" 라고 함!!
예외처리를 하는 목적
- 예외처리를 하지 않고 그대로 예외가 발생되는 경우 프로그램이 비정상적으로 종료될 수 있음
* 예외처리 방법
1. try~catch 문을 이용 (try~with~resource)
2. throws를 이용 (떠넘기기 == 위임한다)
1. UncheckedException
RuntimeException
- 프로그램 실행시 발생되는 예외들
* RuntimeException의 후손들
- IndexOutofBoundsException : 부적절한 인덱스를 가지고 접근시 발생되는 예외
- NullPointerException : 참조변수가 null로 초기화된 상황에서 null에 접근했을때 발생되는 예외
- ArithmeticException : 나누기 연산시 0으로 나누려 할 때 발생되는 예외
- ClassCastException : 허용할 수 없는 형변환이 진행될 때 발생되는 예외
- NegtiveArraySizeException : 배열 할당과 정에서 배열의 크기를 음수로 지정하는 경우 발생되는 예외
=> RuntimeException 관련된 예외는 충분히 예측가능한 상황이 있음
아싸리 애초에 예외 발생이 안되게끔 if문 조건처리 가능
ArithmeticException : 나누기 연산시 0으로 나누려 할 때 발생되는 예외
System.out.print("첫번째 정수 : ");
int num1 = sc.nextInt();
System.out.print("두번째 정수 : ");
int num2 = sc.nextInt();
해결방법 1)
애초에 예외 자체가 발생이 안되게끔 if문으로 조건 검사 => 예외처리 아님!!
System.out.print("첫번째 정수 : ");
int num1 = sc.nextInt();
System.out.print("두번째 정수 : ");
int num2 = sc.nextInt();
int result = 0;
if(num2 != 0) {
result = num1 / num2;
}
System.out.println("안녕하세요. 반갑습니다. 계산결과를 알려드리겠습니다.");
System.out.println("result : " + result);
해결방법 2)
예외처리 : 예외가 "발생했을때" 실행할 내용을 미리 작성해놓는 방법
[표현법]
* try catch 방법
try {
예외가 발생될 수 있는 구문;
}catch(발생될예외클래스 매개변수){
해당 예외가 발생됐을 경우 실행할 구문;
}
System.out.print("첫번째 정수 : ");
int num1 = sc.nextInt();
System.out.print("두번째 정수 : ");
int num2 = sc.nextInt();
try {
int result = num1 / num2; // 4, 0
System.out.println("result : " + result);
}catch(ArithmeticException e) { // 예외를 낚아챔
System.out.println("0으로 나눌 수 없습니다.");
// e.printStackTrace(); // 강제로 오류난 이력 보고자할때 실행하는 구문
}
System.out.println("프로그램을 종료합니다.");
NegativeArraySizeException : 배열 할당 과정에서 배열의 크기를 음수로 지정하는 경우 발생되는 예외
ArrayIndexOutofBoundsException : 배열에 부적절한 인덱스를 가지고 접근시 발생되는 예외
InputMismatchException : 정수로 입력해야 되는데 문자로 입력한 경우 발생되는 예외
System.out.print("배열의 크기 : ");
int size = sc.nextInt();
int[] arr = new int[size];
System.out.println("100번 인덱스 값 : " + arr[100]); // arr[100]에 의해 적어도 배열의 크기는 101이 돼야함
해결방법 1)
if문으로 아싸리 예외자체가 발생이 안되도록 먼저 막는 방법
System.out.print("배열의 크기 : ");
int size = sc.nextInt();
int[] arr = new int[size];
// if문으로 아싸리 예외자체가 발생이 안되도록 먼저 막는 방법
if(size >= 101) {
System.out.println("100번 인덱스 값 : " + arr[100]);
}
해결방법 2)
예외처리 : 예외가 "발생했을때" 실행할 내용을 미리 작성해놓는 방법
System.out.print("배열의 크기 : ");
int size = sc.nextInt();
try {
int[] arr = new int[size];
System.out.println("100번 인덱스 값 : " + arr[100]);
}catch(NegativeArraySizeException e) {
System.out.println("배열의 크기로 음수를 제시할 수 없습니다.");
}catch(ArrayIndexOutOfBoundsException e) {
System.out.println("부적절한 인덱스로 접근했습니다.");
}catch(InputMismatchException e) {
System.out.println("정수가 아닌 값을 입력하셨습니다.");
}
// 다중 catch 블럭 작성 가능
System.out.println("프로그램을 종료합니다.");
다형성을 이용해서 모든 예외를 묶어서 처리할 수 있음.
단, 부모예외클래스와 자식예외클래스를 가지고 catch 블럭을 기술하고자 할 때는 자식예외클래스 catch 블럭이 위에 있어야 함!!!(아니면 unreachable catch block 오류뜸)
System.out.print("배열의 크기 : ");
try {
int size = sc.nextInt();
int[] arr = new int[size];
System.out.println("100번 인덱스 값 : " + arr[100]);
}catch(InputMismatchException e) { // 굳이 얘를 쓰고 싶다면 부모인 RuntimeException 위에 사용해야됨!! 그렇지 않으면 도달하지 않는다.
System.out.println("정수가 아닌 값을 입력하셨습니다.");
}catch(RuntimeException e) { // 다형성 적용해서 부모타입 예외클래스 작성 가능
// 모든 자식 예외 발생시 다 받아서 처리할 수 있음
System.out.println("예외가 발생되긴 했음.. 배열의 크기가 잘못됐던가, 부적절한 인덱스가 제시됐던가, 정수로 입력을 안했던가...");
}
RuntimeException 관련애들은 UnCheckedException (예외처리구문이 필수는 아님)
if 문 : 애초에 예외자체가 발생되기 전에 소스코드로 핸들링 하는거임 (예외처리구문이 아님)
try-catch문 : 예외가 "발생했을경우" 처리해주는 구문을 작성해두는 것 (예외처리 구문임)
예측가능한 상황은 if 문으로 조건검사로 해결하는게 권장사항임!
부득이하게 조건문으로 핸들링이 안되는 구문은 예외처리 구문으로 작성해둘 것!
2. CheckedException
CheckedException은 반드시 예외처리 해야되는 예외들임
=> 조건문 미리 제시할 수 없음 (왜? 예측이 불가한 곳에서 문제가 발생하기 때문에 미리 예외처리 구문을 작성해놓아야 함)
=> 외부 매개체와 입출력이 일어날 때 발생됨!! (입력 Input 출력 Output => IOException)
public void method1() {
method2();
}
public void method2() {
// Scanner와 같이 키보드로 값을 입력받을 수 있는 개체 (단, 문자열로 읽어들여짐)
// 스캐너 이전의 방식 => 정수, 실수 안됨 무조건 문자만 받을 수 있음
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 1. try~catch 문 : 여기 이 자리에서 곧바로 예외를 처리하겠다.
// try{} : 예외가 발생할 가능성이 있는 코드를 작성
// catch(발생될예외클래스 매개변수){} : try 구문 내에서 예외가 발생했을 경우 어떨게 처리할껀지에 대한 내용 작성
System.out.print("아무거나 입력해주세요 : ");
try {
String str = br.readLine(); // 컴파일 에러 예외처리없으면 무조건 에러발생
System.out.println(str);
} catch (IOException e) {
e.printStackTrace();
}
}
// 2. throws : 지금 이 자리에서 예외를 처리하지 않고 이 메소드를 호출하는 곳으로 예외처리 떠넘기겠다.(위임)
String str = br.readLine(); // 애초에 readLine() 메소드에서 throw IOException 하고 있음 (떠넘기고 있음)
System.out.println(str);
예외클래스 | 예외발생시점 | 예외처리 | |
UnCheckedException | RuntimeException | 런타임에러 | 선택(개발자가 케바케로 처리 => if 문을 통해 애초에 예외가 발생안되도록 / 예외처리구문 |
CheckeedException | RuntimeException 외 | 컴파일러에러(빨간줄) | 필수(조건문 안됨!! 무조건 예외처리구문) |