국비/Java

[13-1] Java - Exception 예외처리

제발 취업하게 해주세요 2022. 4. 25. 22:21
Error 에러의 종류
* 시스템 에러
- 컴퓨터의 오작동으로 발생하는 에러
=> 소스코드로 해결이 안됨 (심각한 오류)

* 컴파일에러
- 프로그램 실행 전 소스코드상의 문법적인 문제로 발생하는 에러
=> 소스코드 수정으로 해결 (빨간 줄로 오류를 알려줌)

* 런타임에러
- 프로그램 실행 중 발생하는 에러
=> 소스코드상 문법적인 문제는 없으나 에러 발생
=> 개발자가 예측 가능한 경우 제대로 처리를 해놓지 않은 경우
=> 사용자의 잘못일 가능성도 있음

* 논리에러
 : 소스코드상 문법적인 문제도 없고, 실행했을 때 문제가 발생하지는 않지만 프로그램상 의도가 맞지 않는 것
=> 기획과 설계가 잘못 되었을 경우 발생

예외, 예외처리
* 예외
 : 시스템에러를 제외한 나머지 컴파일, 런타임, 논리에러 같이 비교적 덜 심각한 에러들, 특히 런타임 에러를 주로 예외로 다룬다

* 예외처리
 : 예외가 발생했을 경우에 대비해서 처리하는 방법을 정의해두는 것

1. try ~ catch문 
[표현법]
try {
       예외가 발생될법한 구문, ex ) (num1 / num2)
  } catch (발생할예외클래스이름 변수명(일종의매개변수)){
             ArithmeticException      e

         해당 예외가 발생했을 때 실행할 구문
     }

2. throws (떠넘기기)
 - 메소드를 호출한 곳으로 떠넘겨 처리함
 메소드명() thrwos 예외클래스이름{
RuntimeException 프로그램실행시 발생되는 예외들
RuntimeException의 자식클래스
- ArrayIndexOutOfBonusException : 배열의 부적절한 인덱스로 접근할 때 발생하는 예외
- NegativeArraySizeException : 배열의 크기를 음수로 지정할 경우 발생하는 예외
- ClassCastException : 허용할 수 없는 형변환이 진행될 경우 발생하는 예외
- NullPointException : 주소값 객체를 참조했을 때 null이 들어있을 경우 발생하는 예외
- ArithmeticException : 나누기 연산을 0으로 나누면 발생하는 예외
...
RuntimeException과 관련된 예외들은 개발자가 예측이 가능함
>> 조건문으로 해결 가능, 굳이 예외처리를 할 필요가 엇다
// ArithmeticException
	public void method1() {
		// 사용자에게 두개의 정수값을 입력받아서 나눗셈 결과 출력
		
		Scanner sc = new Scanner(System.in);
		
		System.out.println("정수 두 개를 입력하세요");
		System.out.print("정수 1 : ");
		int num1 = sc.nextInt();
		System.out.print("정수 2 : ");
		int num2 = sc.nextInt();
		
		// 방법 1. 조건문으로 처리
		if(num2 != 0) {
			System.out.println("나눗셈 결과 : " + num1 / num2);
		} else {
			System.out.println("0으로 나눌 수 없습니다.");
		}
		System.out.println("프로그램을 종료합니다.");
		
		
		
		// 방법2. 예외처리 구문으로 해결, 예외가 발생했을 경우 실행할 내용을 정의해두는 것
		try {
			System.out.println("나눗셈 결과 : " + (num1 / num2));
			// 문제가 발생하면 문제가 발생한 지점에서 멈춤
			System.out.println("문제발생안했어"); // 문제발생시 출력 안됨
			
		} catch(ArithmeticException e) { // 수학적오류
			// 문제가 없으면 catch문 건너뜀
			System.out.println("0으로 못나눠");
			e.printStackTrace(); //오류를 추적할 수 있는 메소드 //java.lang.ArithmeticException: / by zero
			// 현재 오류가 발생한 정보를 볼 수 있고, 어디서 에러가 났는지 나열해준다.	
			// 개발단계, 테스트 단계에서만 써야한다!!
			// 에러문구를 사용자가 보면 안됨!!!!!!!!!
		}
		System.out.println("프로그램 종료");	
	}
    
    -------------------------------------------------------------------------------------
    //다중 catch 블록
	public void method2() {
		
		/*
		 * 다중 catch블록
		 * catch할 예외가 여러 개일 경우 주로 사용
		 * 
		 */
		
		Scanner sc = new Scanner(System.in);
		System.out.println("정수 입력(0제외) : ");
		
		try {
			int num = sc.nextInt(); // 정수입력했더니 이상한거 입력함
			System.out.println("나눗셈 결과 : " + (100 / num)); // 0하지 말랬는데 0넣음
		}catch(InputMismatchException a) { //1. 우선적으로 입력받은게 정수인지 판단
			System.out.println("정수만 입력하세요");
		}catch(ArithmeticException e) { //2. 정수라면 0인지 아닌지 판단
			System.out.println("0은 입력할 수 없어요");
		}
		System.out.println("프로그램 종료");
	}
-----------------------------------------------------------------------------------------

	public void method3() {
		// 배열 활용
		// ArrayIndexOutOfBoundsException : 배열의 부적절한 인덱스로 접근할 때 발생하는 예외
		// NegativeArraySizeException : 배열의 크기를 음수로 지정할 경우 발생
		
		
		// 사용자로부터 배열의 크기를 입력받아서 배열 만들기
		// 100번째 인덱스의 값을 출력하기
		
		Scanner sc = new Scanner(System.in);
		
		System.out.println("배열의 크기를 입력하세요");
		try {
			int num = sc.nextInt(); // 1. InputMismatchException
			int [] arr = new int[num]; // 2. NegativeArraySizeException
			System.out.println(arr[100]); // 3. ArrayIndexOfBoundException
		
			// 다중 catch문을 작성시 범위가 작은 자식타입의 예외클래스 먼저 기술해야 함
			} catch(InputMismatchException e) {
				System.out.println("정수넣어");
			} catch(NegativeArraySizeException e) {
				System.out.println("양수넣어");
			} catch(ArrayIndexOutOfBoundsException e) {
				System.out.println("100칸안돼");
				
			}  catch(RuntimeException e) { // 위의 세 가지 오류 모두 RuntimeException 자식클래스
			System.out.println("배열이 이상해");
			// 뭉뚱그려서 포괄적인 오류 처리만 가능하다 ==> 단점
			// 예외가 발생하긴 했는데 오류가 정확히 뭔지 모름
		} 
		
		
	}
CheckedException
- 문법적으로 반드시 예외처리를 해줘야 하는 예외들
- 즉, 예측이 불가한 곳에서 발생하기 때문에 미리 예외처리 구문을 작성해야한다
=> 주로 외부매체와 어떤 입출력시 발생함
public void method1(){
	try{
    	method2();
    }catch(IOException e) {
        System.out.println("예외가 발생했어요");
    }
}


public void method2() throws IOException{ //던지기
	System.out.println("아무 문자열이나 입력해주세요")
    
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in);
    
    // 여기(method2)에서 말고 이 메소드를 호출한 곳(method1)에 예외를 떠넘겨서 처리하겠다
    String str = br.readLine();
    System.out.println("문자열의 길이 :" + str.length());
    }

public static void main(String[] args) throws IOException {

		B_CheckedException b = new B_CheckedException();
		b.method2();
	}
BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
 => 스캐너 친구, 키보드로 값을 입력받을 수 있는 객체(단, 문자열만 가능)
String str = br.readLine();
 => Scanner nextLine과 같은 역할