ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 예외 처리(Exception)
    개발/자바JAVA 2024. 2. 5. 12:19

    ▶프로그램 오류

       > 프로그램 수행 시 치명적 상황이 발생하여 비정상 종료 상황이 발생한 것, 프로그램 에러라고도 함.

     

     

      ▶오류의 종류

        ◆ 시스템 에러 : 컴퓨터의 오작동으로 인해 발생하는 에러
                  > 개발자가 소스코드로 해결 안됨.(제일 심각함)
                   
        ◆ 컴파일 에러 : 소스코드가 컴파일 되는 시점에서 발생하는 에러(소스코드 상의 문법적인 문제로 발생)
                 > 소스코드 수정으로 해결(빨간 밑줄로 오류를 표시해줌)
                  
        ◆ 런타임 에러 : 컴파일된 프로그램 코드가 "실행" 되는 시점에서 발생하는 에러
                  (소스코드 상의 문제는 없는데, 실행중에 발생)
                 > 사용자의 잘못일수도 있고, 개발자가 예측가능한 경우를 제대로 처리 안해놓은 잘못일수도 있음.
                  

        ◆ 논리 에러 : 소스코드 상의 문법적인 문제도 없고, 실행했을 때도 굳이 문제가 되지 않지만,  
                               프로그램 의도 상 내가 의도하지 않은 대로 코드가 흘러갈 경우

     

        ▷이러한 "예외"들이 "발생" 했을 경우에 대비해서 "처리" 하는 방법을 정의해두는 것을 "예외처리" 라고 함!!!!
     
        ▷ 예외처리 해야하는 이유 : 예외 발생 시 프로그램이 비정상적으로 종료되는 상황을 막고자 하기 위함
                          (조건문 같은 느낌임)

     

    조건문으로 충분히 해결 가능 : 예외 자체가 발생 안되게끔 개발자가 소스코드로 핸들링 하는 것(예방, 예외처리x)
    예외처리 구문으로 해결 가능 : 예외가 발생했을 경우를 대비해서 실행할 구문을 정의해두는것(수습)

     

    ▶예외 클래스 계층 구조

      > Exception Error 클래스 모두 Object 클래스의 자손이며 모든 예외의 최고 조상은 Exception 클래스

     

    unchecked : 예외처리 안해도 됨.

    checked : 예측 불가능한 오류/ 예외처리를 무조건 해야함

     

     

    ▶ UncheckedException

      > 프로그램 실행 시 발생되는 예외 클래스들의 부모클래스

         -예측이 가능한 상황 : 조건문으로 해결(권장)
      > RuntimeException관련된 예외는 충분히 예측 가능하기 떄문에 조건문으로 해결하는 것을 권장
          --> 즉, 예외처리가 필수가 아닌 "Unchecked Exception" 계열임!!

     

     

    ◈   RuntimeException 의 자식클래스들


     1. ArrayIndexOutOfBoundsException : 배열의 부적절한 인덱스로 접근할 때 발생
     2. NegativeArraySizeException : 배열의 크기를 음수로 지정할 경우 발생
     3. ClassCastException : 허용할 수 없는 형변환이 진행될 경우 발생(상속관계 아닐때)
     4. NullPointerException : 참조할 주소값이 null인데 접근하려고 할때 발생 
     5. ArithmeticException : 나누기 연산시 0으로 나눌 때 발생.


      >이러한 RuntimeException 과 관련된 예외는 충분히 예측 가능한 상황임.
        --> 예외 자체가 발생이 애초에 안되게끔 "조건문" 으로 충분히 해결 가능한 오류들임.
            =굳이 "예외처리" 를 안해도 처리 가능함 ( == Unchecked Exception)

     

     

     

    ArithmeticException(나누기 연산시 0으로 나눌때 발생)

    public void method1() {
    		
    		System.out.println("첫번째 정수 : ");
    		int num1 = sc.nextInt();
    		sc.nextLine();
    		
    		System.out.println("두번째 정수(0제외) : ");
    		int num2 = sc.nextInt();
    		sc.nextLine();
    		
    		System.out.println("결과 : " + (num1/num2));
    		
    		System.out.println("프로그램 종료");
    		}

     

    >두번째 정수에 0을 입력하면 이 오류가 뜬다

     

       

    해결방법1 ) 그냥 조건문으로 처리해도 되지만(예방) 이는 예외사항을 미리 알 경우만 사용가능하다.

     

    해결방법2 ) 예외가 발생했을 경우를 대비해서 실행할 내용을 정의해 두는것(수습)

     

        바로 try ~catch문 을 이용하는 것.

          : 예외가 발생할 법한 구문을 실행시키고, 거기서 예외가 발생한다면 그 때 실행할 구문을 선택적으로 실행될 수 
             있게끔 흐름을 잡아채는 구문임.

     

    [표현법]
       try{
         
       예외가 발생할법한 구문
       
       }catch(발생할예외클래스 변수명){
                          (관례상e)
                           
        해당 예외가 발생할 경우 실행할 구문
       
        }

    public void method1() {
    		
    		System.out.println("첫번째 정수 : ");
    		int num1 = sc.nextInt();
    		sc.nextLine();
    		
    		System.out.println("두번째 정수(0제외) : ");
    		int num2 = sc.nextInt();
    		sc.nextLine();
    			
    		try {
    			System.out.println("결과 : " + (num1/num2));
    			
    		}catch(ArithmeticException e) {
    			System.out.println("0으로는 나눌 수 없습니다.");
    			e.printStackTrace(); // 어디서 예외가 발생했는지 추적하기 위함(개발단계에서 쓰임)
    		}
    		System.out.println("프로그램 종료");
    		
    		
    		}

     

    이렇게 try ~catch 문으로 잡아주면 된다.

     

     

      처리할 예외가 2개이상일 경우(다중catch블럭)

    public void method2() {
    		
    		try {
    		System.out.println("정수 입력(0제외) :");
    			int num = sc.nextInt(); // 정수 이외의 값을 입력하면 오류가 발생할 수 있음.
    			sc.nextLine();
    			
    			System.out.println("나눗셈 연산 결과 : " + (10/num)); //num이 0이면 오류가 발생함.
    		}catch(ArithmeticException e) {	//연
    			System.out.println("0으로 나눌 수 없습니다.");
    		}catch(InputMismatchException e) { // 정수값이 올바르지 않을 경우 오류
    			System.out.println("정수를 제대로 입력해야 합니다.");
    			
    		}
    		System.out.println("프로그램 종료");
    	}

    > catch를 하나만 쓸 경우 2가지를 다 잡을 수 없다.

     

    ◈  ArrayIndexOutOfBoundsException : 배열의 부적절한 인덱스로 접근할 때 발생하는 예외

         NegativeArraySizeException : 배열의 크기를 음수로 지정할 경우 발생하는 예외

     

    public void method3() {
    		
    		
    		System.out.println("배열의 크기 : ");
    		int size = sc.nextInt();
    		sc.nextLine();
    		
    		try {
    			int arr[] = new int[size];	
    			//>size가 0보다 작다면 NegativeArraySizeException 발생
    			
    			System.out.println("100번 인덱스 값 : " + arr[100]);
    			//size가 100이하라면 (99번째 방까지 있는 배열이라면)
    			//ArrayIndexOutOfBoundsException 발생
    		}catch(NegativeArraySizeException e) {
    			System.out.println("배열의 크기를 음수로 지정할 수 없습니다.");
    			
    		}catch(ArrayIndexOutOfBoundsException e) {
    			System.out.println("입력한 배열의 크기가 출력할 배열의 값보다 커야합니다.");
    		}
    		
    
    		
    		System.out.println("프로그램 종료");
    	}

     

     

    위와같이 예외처리를 여러가지 쓸 수도 있지만, RuntimeException클래스 하나만 써서, 한번에 처리할 수도 있음!!(다형성)

     

     

    ◈ RuntimeException클래스 하나만 써서, 한번에 처리(다형성활용)

     

    public void method4() {
    		
    		System.out.println("배열의 크기 : ");
    		int size = sc.nextInt();
    		sc.nextLine();
    		
    		try {
    			int arr[] = new int[size];
    			
    			System.out.println("100번 인덱스 값 : " + arr[100]);
    			
    		}catch(RuntimeException e) {
    			 // 다형성을 적용하여 부모 타입의 예외 클래스 하나로 자식타입의 예외를 모두 잡을 수 있음.
    			
    			System.out.println("배열의 크기를 음수로 지정했거나, 부적절한 인덱스로 접근했음.");
    			//catch블럭이 줄어들긴 할테지만, 정확한 종류의 예외를 알려줄 수 없음.
    			
    			
    			
    		}
    		System.out.println("프로그램 종료");
    	}

     

     

      >다형성 적용 및 다중 catch블럭 이용시 주의할 점!!


         해당 catch블럭이 한번 실행되면 -> 아예 try ~ catch 블럭을 빠져나감.
          -> 다중 catch블럭은 작성 순서가 중요함.
              범위가 작은 자식 타입의 예외 클래스 먼저 기술해야함!!.
              (RuntimeException다음에 ArrayIndexOutOfBoundsException이거 못씀.)

     

     

     

    ▶ CheckedException

      > CheckedException 반드시 예외처리를 해줘야 하는 예외들 (즉, 예측 불가한 곳에서 언제 발생할지 모르기 때문에

         미리 예외 처리

     

      > 구문을 작성) >주로 외부 매체와 내 프로그램 사이의 데이터 입출력시 발생함.


      > 선배개발자들이 나한테 throw한게 대부분임. 그래서 빨간 밑줄로 예외처리를 안하면 오류로 알려주는 것임

     

     

    ◈IOException

    public void method2() {
    
    		// Scanner 와 같이 키보드로 값을 입력받을 수 있는 객체(단, 문자열로만 가능)
    		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    
    		System.out.println("아무 문자열이나 입력하세요 : ");
    
    		// String str = br.readLine();
    		// >위 메소드를 호출 시 IOException 가 발생할 수도 있음을 빨간밑줄로(컴파일에러) 알려주고 있음.
    
    		// 1. try~catch문 이용해서 해결
    
    		try {
    			String str = br.readLine();
    
    			// 문자열 길이 출력(str도 지역변수 이기 떄문에 try블록 안에서 놀아야됨)
    			System.out.println("문자열의 길이 : " + str.length());
    
    		} catch (IOException e) {
    
    			System.out.println("예외 발생됨");
    		}
    
    	}

     

    IOException으로 넘길수 있다.

     

     

     

    ◈ throws 이용해 예외처리해서 해결

    public void method3() throws IOException{
    
    		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    
    		System.out.println("아무 문자열이나 입력하세요 : ");
    		String str = br.readLine();
    		
    	}

     

    나를 호출한 부분(메인클래스)으로 떠넘겨준다. 호출한 곳에서(메인클래스) 처리해줘야함.


    만약 method1()에서 호출했다면 거기서 처리해주면 됨!

    이렇게 호출한 곳에서 처리해줄 수 있다!!

     

    만약 여기서도 쓰기 싫다면 또 throws로 떠넘길 수 있다. 하지만 마지막에 받는곳에서 꼭 처리해줘야함!!
    근데!! 메인메소드에서 마지막에서도 죽어도 처리하기 싫다?? 메인 메소드 뒤에 throws IOException 써주면 됨.


     -> main까지 예외처리를 떠넘길 수 있고, main에서도 또 떠넘길 수 있다.

    이렇게 되면 결국 우리의 갓갓 JVM이 예외를 처리해줌.(권장x)

    '개발 > 자바JAVA' 카테고리의 다른 글

    java.util.Date 클래스  (1) 2024.02.11
    String관련 API  (1) 2024.02.11
    기본API(Application Programming Interface)  (0) 2024.02.02
    추상클래스(Abstract Class)  (0) 2024.02.02
    다형성(Polymorphism)  (1) 2024.01.31
Designed by Tistory.