728x90
예외
- 에러에 대한 처리
- 예외처리 메커니즘 제공
- 문제가 될 만한 부분을 사전에 예상하고 → 문제가 발생하면 이렇게 처리하라고 프로그래밍 하는 것
목적: 실행이 멈추지 않게
에러 - 심각한 것 / 예외 - 미약한 것
컴파일러 에러 (Compile-time Error): 문법적으로 틀린 부분, 컴파일 할 때 발생하는 에러
런타임 에러 (& Runtime Exception, 실행 예외): (컴파일 과정에서) 실행 할 때 일어나는 에러 / 프로그램 종료
논리적 에러(Logical Error): 작성 의도와 다르게 동작 / 프로그램 종료 X
주요 실행 예외
- NullPointException (NPE) - null값을 갖는 참조 변수 / dot(.)을 사용했을 때 발생
- ArrayIndexOutOfBoundsException - 배열의 인덱스 범위 초과
- NumberFormatException - 문자열→숫자로 변경하는 경우 발생
- ClassCastException - 클래스 형변화 에러
예외 처리 방법1: try ~ catch ~ finally
try {
모든 프로그램 코드
} catch (Exception e) {
에러 발생시 처리할 내용
} finally {
무조건 실행
}
- catch 블럭{ } 여러개 가능 = 다중 catch
- try 괄호 생략 불가
다중 catch
- 둘 이상의 예외 처리
주의! 상위 예외 클래스가 하위 예외 클래스보다 아래쪽에 위치해야 함
예외 처리 클래스도 상속 관계를 가지는데, 주의하지 않으면 자식 클래스들이 실행 안됨
상속관계 확인: ctrl + t
Exception은 예외 클래스들의 부모클래스
예제
더보기
RunTimeEx - 실행예외 되는 경우 4가지
package day10.exception.trycatch;
import day06.inherit.good.Person;
public class RunTimeEx {
public static void main(String[] args) {
// 실행예외(runtime)
// String s = null;
// if(s != null) {
// s.charAt(0);
// }
// ArrayIndexOut
// int[] arr = {1, 2, 3};
// arr[5] = 10;
// ClassCast
// Object o = new Object();
// Person p = (Person)o; // Person으로 생성된 객체만 Person으로 캐스팅 가능
// NumberFormat
// String s = "홍길동";
// Integer.parseInt(s); // 숫자로 바꿔주는 기능
}
}
TryCatchEx01
package day10.exception.trycatch;
public class TryCatchEx01 {
public static void main(String[] args) {
int a = 10;
int b = 0;
System.out.println(a + b);
try {
System.out.println(a / b);
System.out.println("이 문장은 실행이 될까요?"); // 실행 안됨, 위에서 에러 발생시 catch영역으로 바로 넘어감
// catch뒤에는 해당 예외를 처리할 수 있는 예외 종류가 들어갑니다.
} catch (Exception e) {
System.out.println("0으로 나눌 수 없습니다");
}
System.out.println(a - b);
}
}
----------------------출력-------------------
10
0으로 나눌 수 없습니다
10
- a+b, a-b의 경우는 예외가 없으므로 그대로 출력
- 에러, 예외가 생길 것 같은 구문에 try-catch로 예외시 나올 문장(0으로 나눌 수 없습니다.) 출력
- try{}의 경우 에러가 발생하는 순간 아래 부분은 실행이 안되고 바로 catch 영역으로 넘어감
TryCatchEx02
package day10.exception.trycatch;
public class TryCatchEx02 {
public static void main(String[] args) {
String[] arr = {"홍길동", "이순신", "홍길자"};
int i = 0;
while(i < 4) {
try {
System.out.println(arr[i]);
} catch (Exception e) {
System.out.println("범위를 벗어났습니다");
} finally {
System.out.println("이 문장은 예외 여부와 상관없이 항상 실행됨");
}
i++;
}
}
}
---------------------------출력--------------------------
홍길동
이 문장은 예외 여부와 상관없이 항상 실행됨
이순신
이 문장은 예외 여부와 상관없이 항상 실행됨
홍길자
이 문장은 예외 여부와 상관없이 항상 실행됨
범위를 벗어났습니다
이 문장은 예외 여부와 상관없이 항상 실행됨
- String[] 배열 타입 arr에 초기화 된 값이 있음
- while 반복문으로 i = 0 ~ 3까지 돌면서 배열값이 출력
- 에러가 발생하면 catch 영역의 범위를 벗어났다는 문구 출력
- finally영역은 예외 여부와 상관없이 반복을 돌때마다 출력
MultiCatchEx01 - 복습
package day10.exception.trycatch;
public class MultiCatchEx01 {
public static void main(String[] args) {
// main의 args 사용방법
// run -> run configuration -> argments탭에 -> ${string_prompt}
try {
// main 메소드의 String[] args는 사용자가 입력한 값(문자열)을 args(파라미터)에 할당하는 것을 의미
String data1 = args[0];
String data2 = args[1];
int n1 = Integer.parseInt(data1); // String타입의 숫자를 int타입으로 변환
int n2 = Integer.parseInt(data2);
System.out.println("두 수의 합: " + (n1 + n2));
String s = null;
s.charAt(0); // string으로 저장된 문자열 중에서 한글자만 선택해서 char타입으로 변환
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("매개값은 2개 입력하세요");
} catch (NumberFormatException e) {
System.out.println("매개값은 숫자로 입력하세요");
} catch (Exception e) { // 어떤 실행 예외든 처리가 가능 (예외의 부모) (클래스의 상속 관계: ctrl + t)
System.out.println("기타 예외 입니다");
}
// System.out.println(args[0]);
// System.out.println(args[1]);
}
}
실행을 여기서도 가능
TryCatchEx03 - 엔터 개행 제거
package day10.exception.trycatch;
import java.util.Scanner;
public class TryCatchEx03 {
public static void main(String[] args) {
// 입력과 예외처리
// 0을 입력하기 전까지 숫자를 입력
Scanner scan = new Scanner(System.in);
while(true) {
try { // 예외 발생 가능성이 있는 코드
System.out.print(">");
// 1. int num = Integer.parseInt( scan.nextLine() ); // nextLine은 엔터값을 포함해서 다시 받아줌
int num = scan.nextInt(); // 정수를 받음 (문자 입력하면 프로그램 멈춤, 예외, 에러 발생)
if(num == 0) break; //
// try 내부의 코드에서 에러 발생시 예외를 받아옴(catch가 실행되는 동안 프로그램 멈추지 않음)
} catch (Exception e) {
System.out.println("숫자로 입력하세요");
// 2. scan = new Scanner(System.in); // 내풀이
scan.nextLine(); // 3. 엔터개행을 제거
}
}
}
}
--------------------------출력------------------------
>1
>나
숫자로 입력하세요
>
- nextint로 정수를 입력받고, 엔터를 치면 개행문자는 제거하지 않은 채 그대로 남겨줌
- 남은 개행문자가 nextLine으로 입력 처리되어 문자를 받지 못하고 바로 개행
- 오류를 해결하려면 nextLine전 scan.nextLine을 한번더 작성하여 개행문자 제거
Quiz16 - up/down 게임, 엔터 개행 제거
package quiz16;
import java.util.Scanner;
public class MainClass {
public static void main(String[] args) {
/*
* up down게임
*
* 1~100까지의 임의의 숫자를 1번 생성
* 반복문 안에서 스캐너를 이용해서 정답을 입력받습니다.
*
* 랜덤수가 입력받은 값보다 작으면 "더 큰수를 입력하세요"
* 랜덤수가 입력받은 값보다 크면 "더 작은수를 입력하세요"
*
* 정답이라면 시도횟수: x회 를 출력하고 종료
*
* 만약에 숫자가 아닌값이 들어온다면 예외를 처리하고, 다시 입력받으세요
*/
Scanner scan = new Scanner(System.in);
int ran = (int)((Math.random()*100) + 1);
int count = 0; // 시도횟수
while(true) {
try {
System.out.println("정답입력>");
int answer = scan.nextInt();
count++;
if(answer == ran) {
System.out.println("정답");
System.out.println("시도 횟수: " + count);
break;
} else if(answer > ran) {
System.out.println("더 작은수를 입력해라");
} else
System.out.println("더 큰 수를 입력해라");
} catch (Exception e) {
System.out.println("숫자로 입력해라");
scan.nextLine(); // while안 무한루프, catch영역에 들어오면 엔터를 강제로 제거
count++; // 잘못입력한 값도 시도횟수로 들어가야 하므로
}
}
}
}
예외 처리 방법2: throws (예외 떠넘기기)
- throws는 직접 처리하지 않고, 메서드 or 생성자를 호출한 곳으로 예외를 떠넘김
= 메서드 호출자에게 예외를 던지는 방법 - 예외가 일어나면 통으로 메서드 종료
- throws 키워드가 붙은 메서드는 반드시 try 블록 내부에서 호출되어야 함.
- main도 throws 사용 가능
throws는 예외가 날 수 있는 프로그램 코드 → try-catch로 묶고 쓰라고 강요!!
예외 강제 발생: throw
- 예외를 직접 생성하는 방법으로 잘 사용되지는 않음
- 예외를 강제 발생시키며 메서드를 강제 종료
ThrowsEx01
e.printStackTrace(): 예외 발생 당시의 호출스택(Call stack)에 있던 메소드의 정보와 예외 결과를 화면에 출력
package day10.exception.throws_;
public class ThrowsEx01 {
public static void main(String[] args) {
// 메서드에서 예외처리 - throws
// throws 구문이 붙어있는 메서드 ar 생성자를 호출할때는 예외를 대신 처리애햐 합니다.
// 즉 메서드안에서 예외처리를 강요할 때 사용합니다.
try { // 호출문장 안에서 예외처리 해줘야 함
greeting(0);
greeting(1);
greeting(2);
greeting(3);
greeting(4);
} catch (Exception e) {
System.out.println("배열 참조를 벗어났습니다");
}
System.out.println("------------------");
try {
calc(0);
} catch (Exception e) {
System.out.println("\"0으로 나눌 수 없습니다.");
}
System.out.println("------------------");
try {
greeting(5);
} catch (Exception e) {
// 예외처리를 하면 예외의 내용을 알수가 없기 때문에,
// 예외의 내용을 확인하기 위해서 catch영역에서는 항상 사용합니다.
e.printStackTrace();
}
System.out.println("프로그램 정상 종료");
} // main의 끝
// static
private static String[] arr = {"안녕하세요", "hello", "니하오", "곤니찌와" };
public static void greeting(int index) throws Exception {
System.out.println(arr[index]);
}
public static void calc(int num) throws ArithmeticException {
System.out.println(10 / num);
}
}
ThrowsEx02 - 1
package day10.exception.throws_;
public class ThrowsEx02 {
// 생성자
public ThrowsEx02() throws Exception {
System.out.println("생성자호출");
aaa();
System.out.println("생성자종료");
}
public void aaa() throws Exception {
System.out.println("aaa시작");
bbb(1);
System.out.println("aaa종료");
}
public void bbb(int i) throws Exception{
System.out.println("bbb시작");
// try {
// System.out.println(i / 0); // 예외
// } catch (Exception e) { }
System.out.println(i / 0); // 예외
System.out.println("bbb종료");
}
}
// MainClass
package day10.exception.throws_;
public class MainClass {
public static void main(String[] args) {
try {
ThrowsEx02 ex = new ThrowsEx02();
} catch (Exception e) {
System.out.println("0으로 나눌 수 없습니다");
}
}
}
-------------------------호출---------------------
생성자호출
aaa시작
bbb시작
0으로 나눌 수 없습니다
- ThrowsEx02 - "생성자호출" - aaa() - "aaa시작" - bbb(1) - "bbb시작" - i/0 예외발생 - main의 "0으로 나눌 수 없습니다"문구 출력 - 종료
ThrowsEx02 - 2
package day10.exception.throws_;
public class ThrowsEx02 {
// 생성자
public ThrowsEx02() throws Exception {
System.out.println("생성자호출");
aaa();
System.out.println("생성자종료"); // aaa()가 끝나고 실행
}
public void aaa() throws Exception {
System.out.println("aaa시작");
try {
bbb(1);
} catch (Exception e) {
System.out.println("0으로 나눌 수 없습니다");
}
System.out.println("aaa종료"); // bbb()가 끝나고 실행
}
public void bbb(int i) throws Exception{
System.out.println("bbb시작");
// try {
// System.out.println(i / 0); // 예외
// } catch (Exception e) { }
System.out.println(i / 0); // 예외
System.out.println("bbb종료");
}
}
// main은 같음
-------------------------호출---------------------
생성자호출
aaa시작
bbb시작
0으로 나눌 수 없습니다
aaa종료
생성자종료
- ThrowsEx02 - "생성자호출" - aaa() - "aaa시작" - bbb(1) - "bbb시작"- 예외발생 - main의 "0으로 나눌 수 없습니다"문구 출력 - (bbb는 뒷부분 실행 X) - aaa()안의 bbb(1)실행 후 "aaa종료" - 같은 방식으로 위의 "생성자종료"
quiz16 - calculator
package quiz16;
import java.util.Scanner;
public class Calculator {
public static int input() throws Exception {
/*
* 1. 스캐너 정수 2개를 입력을 받습니다.
* 2. 입력된 값이 정수라면 합계를 반환합니다.
* 3. 예외가 발생할 수 있는 상황이라면 throw를 이용해서 메서드를 종료하고 예외메시지를 전달해주면 됩니다
* 4. scan.close() 는 finally 문장에서 사용하세요
* 합계반환, 에러메시지
*/
// Scanner scan = null; 변수를 밖에 선언, 지역변수는 초기화가 필수
// try안에 scan = new Scanner(System.in); 아래와 같음
Scanner scan = new Scanner(System.in);
try {
System.out.println("정수 입력1> ");
int a = scan.nextInt();
System.out.println("정수 입력2> ");
int b = scan.nextInt();
int sum = 0;
sum = a + b;
System.out.println("정수 합계: " + sum);
return sum;
} catch (Exception e) {
throw new Exception("정수로 입력해라"); // 예외생성, throw문제가 생기면서 input()옆에 throws Exception 추가
} finally {
scan.close();
System.out.println("입력을 종료");
}
}
}
- Scanner scan = new Scanner(System.in);
∥ - Scanner scan = null; (변수를 밖에 선언, 지역변수는 초기화가 필수)
try안에 scan = new Scanner(System.in); - throw new Exception("정수로 입력해라");
예외생성, throw문제가 생기면서 input()옆에 throws Exception 추가
package quiz16;
public class MainClass2 {
public static void main(String[] args) {
try {
Calculator.input();
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
} finally { // 여기서는 없어도 됨
System.out.println("입력을 종료합니다");
}
}
}
- main에서 Calculator.input(); 출력
- 예외구문 System.out.println(e.getMessage()); : throw new Exception에 적은 출력
오늘 하루
더보기
기억에 남는 부분
- main과 method에서 한꺼번에 try~catch 구문 사용 가능
- throws 키워드가 붙은 메서드는 반드시 try 블록 내부에서 호출 필수
어려운 부분
- nextInt, nextLine 개행문자 저장되는 부분 살짝 헷갈리지만 알겠음
- ThrowsEx02 부분 throws가 돌아가는 순서 확인
문제 해결 부분
- quiz16.Calculator class, main 두 부분에 예외 설정 가능
e.printStackTrace();, System.out.println(e.getMessage()); 사용
728x90
'프로그래밍 언어 > Java' 카테고리의 다른 글
[Java] API_ java.util (Arrays 클래스 - search, date, calendar, random) (0) | 2022.10.25 |
---|---|
[Java] API_ java.lang (문자열, Math 등) (0) | 2022.10.18 |
[Java] interface (0) | 2022.10.14 |
[Java] 제어자 (static, final, abstract) (0) | 2022.10.13 |
[Java] 키워드 this & super, 접근제한자(public, private) (0) | 2022.10.07 |