Joslynn의 하루

대용량 웹서비스를 위한 MSA Full-Stack 개발자 양성 과정 -13일차 노트 필기_예외 처리_220803 본문

MSA Full-Stack 개발자 양성과정/Java

대용량 웹서비스를 위한 MSA Full-Stack 개발자 양성 과정 -13일차 노트 필기_예외 처리_220803

Joslynn 2022. 8. 3. 18:07

Exception

Error: 치명적인 오류, 개발자가 해결할 수 없는 부분;

Exception: 개발자의 코드에 의해 적절하게 대처가 가능한 예외


Exception 종류

check 예외(일반 예외) - 무조건 예외처리 필요, 예외 처리 없이는 컴파일조차 안 됨;

비check 예외 (RunTimeException)- 실행 도중 발생하는 오류(런타임 종료), 예외 처리가 선택적;

                         컴파일시 발견 어려움;

 

 

**예외처리는 미리 예외가 발생 가능성이 있는 종류를 미리 처리해줌으로써 예외가 발생한 부분은 어쩔 수 없지만 프로그램이 끝까지 실행될 수 있도록 하는 것;

 


Exception 처리 방법

1) 직접 처리 방법 (try, catch, finally)

    try {

        // 예외 발생 가능성이 있는 코드;

    } catch(XxxException 변수 이름) {

        // 예외가 발생했을 때 해야하는 기능 작성;

    } catch(XxxException 변수 이름) {

        // 예외가 발생했을 때 해야하는 기능 작성;
        //ex> IO, JDBC의 닫기 기능;

    } ...
    
    finally{
    
    	// 예외 발생 여부와 상관없이 무조건 해야 하는 영역;
    
    }
    
    *catch 블럭 여러 개 작성할 때는 반드시 서브 클래스부터 작성한다.
    *예외는 다형성 가능; // 예외의 최고 조상: Exception
    *try 단독 사용불가; 반드시 try와 catch, try와 finally함께 사용해야 한다.
    
    try {
    } finally(){
    }
    
    try {
    } catch(){
    }
    
    try {
    } catch{
    } finally(){
    }

**주의사항

1. catch 블럭 여러 개 작성할 때는 반드시 서브 클래스부터 작성한다.
    : 예외는 다형성 가능; // 예외의 최고 조상: Exception

    : Exception이 먼저 올 경우, 여기에서 모든 예외가 다 잡히면서 서브 클래스의 실행되야 할 문장이 실행되지 못하는 경우가 있다. 

2. try 단독 사용불가; 반드시 try와 catch, try와 finally함께 사용해야 한다.

 

 

직접 처리 방법 예제1)

public class ExceptionExample {

	public static void main(String[] args) {
		System.out.println("**************시작하기**************");
		try{
			String param = args[0]; // ArrayIndexOutOfBoundsException
			System.out.println("param = " +param);
			int convertNo = Integer.parseInt(param);
			System.out.println("convertNo = "+ convertNo);
			int result = 100/convertNo;
			System.out.println("나눈 결과: "+result);
		
		} catch(ArrayIndexOutOfBoundsException e) {
			
			// 예외가 발생했을 때 해야 하는 일 작성!!
			System.out.println("e= "+e.toString()); // 발생 예외 객체: 예외메시지
			System.out.println("반드시 인수를 넣어주세요.");
			
		} catch (NumberFormatException e) {
			System.out.println("반드시 숫자만 입력해주세요.");
			System.out.println(e.getMessage());
		} catch (Exception e) {
			System.out.println("예외 발생");
			e.printStackTrace();
			/** printStackTrace: 예외에 대한 정보를 Stack 영역에 보관해놨다가 오류 메시지 한 번에 출력
			 * 예외 정보를 가장 detail하게 출력해 준다. 
			 * 그래서 개발 모드에서 필수적으로 필요하고 운영모드에서는 반드시 제거 (보안을 위해)*/
			
		} finally {
			System.out.println("예외 발생 여부와 상관없이 반드시 실행한다.");
		}
		
		System.out.println("**************** 끝 ****************");
        // finally와의 차이점 비교
	}

}

출력값:


2) 던지기(throws)  ** throw 개념과 구분 필요

public class ThrowsExam {
	
	public void aa(int i) {
		System.out.println("aa 메소드 호출....");
		
		try {
			this.bb(i); // 예외처리 해야 함
		} catch (ArithmeticException e) {
			System.out.println("예외발생: 0으로 나눌 수 없습니다. ");
		}
	
		System.out.println("aa 메소드 끝....");
	}
	
	public void bb (int i) throws ArithmeticException{
		
		System.out.println("bb 메소드 호출....");
			try {
					int result = 100/i; // ArithmeticException 발생 가능성 높음
					System.out.println("나눈 결과: "+result);
			} finally {
				System.out.println("bb 메소드 끝....");
			} // finally 블록은 단독사용 불가
		
	}

	public static void main(String[] args) {
		
		System.out.println("*********** 시작하기 ***********");
		ThrowsExam te = new ThrowsExam();
		te.aa(0);

		System.out.println("*************  끝  *************");

	}

}

: 메소드 선언부 옆에 throws XxxException을 사용한다.

: 예외가 발생하는 메소드가 직접 예외처리 하지 않고, 메소드를 호출하는 주체에게 던지기


**throws의 효용

1) 한번에 예외를 처리하기 위해서 (한곳에 모아서 처리) // 각 메소드마다 예외처리를 하면 반복 코드가 있는데, 한 번에 몰아서 처리하면 소스가 간결해짐

보통 controller 부분에서 예외 처리 // 성공 or fail을 결정 짓는 역할 

 

2) 호출하는 주체가 직접 예외를 관리할 수 있도록 한다.

    메소드가 어떤 예외가 발생할 수 있는지 정보를 제공한다.

 


Throw

1. 프로그램 흐름을 관리하기 위해 강제로 예외를 발생하고 싶을 때: 

     ex) 나이 // 숫자에 음수가 들어오면 예외를 발생하고 싶다.

2. throw 사용 방법:  throw (XxxException) // 예외를 발생시키라는 의미;

 

** Exception: 객체

모든 예외들의 최고 조상 == Exception

package ex0803;

import java.io.IOException;

public class ThrowExam {
	
	public void aa(int i) throws IOException, ArithmeticException{
		System.out.println("aa 호출됨...");
			if (i<0) {
			
            throw new IOException("음수를 입력할 수 없어요"); // 체크 예외 - 예외처리 필수
			
            }
            
			int result = 100/i;
			System.out.println("result= "+result);
	}
	
	public static void main(String[] args) /*throws IO Exception*/{
		try{ 
			new ThrowExam().aa(0);		
		} catch (IOException | ArithmeticException e) {
			System.out.println("예외: "+ e.getMessage());
		} // **중요!!! 여러개의 Exception을 처리할 때, | 연산자로 하나의catch를 통해 여러 예외를 받아줄 수 있다. 
		
		System.out.println("끝");
	
	}

}

 


**사용자 정의 Exception 만들기

class XxxException extends 예외객체 {

 

}

: 예외 객체 선택 기준 - check Exception || 비check Exception(RunTime Exception)

 

ex) 예외처리 필수

class XxxException extends Exception{  }

ex) 예외처리 선택

class XxxException extends RuntimeException{  }

 

new XxxException(  ); // 부모의 기본 생성자 호출;

throw e;

 

/**체크 예외를 상속받은 존재하지 않는 ID 예외*/
class NotExistIDException extends Exception {

	NotExistIDException(){
    	super();
    }
    
    NotExistIDExcepton(String message){
    	super(message);
        // 예외 메시지를 저장 & catch 블록에서 getMessage 메소드의 리턴값으로 얻을 수 있음;
    }
}

 


+ 참조 내용

난수 발생 전용 class

import java.util.Random;

class RandomNo {
	public static void main (String [] args){
		Random rd = new Random(); 
		for(int i=0; i<10; i++) {
			//int age = (int)(Math.random()*55)+1;
			int age = rd.nextInt(55)+1; // 1~55
		}
    }
}

 

Comments