Exception 예외 처리의 개념, 예외 발생 상황, 예외 클래스(처리 메서드)

Yeppi's 개발 일기·2022년 5월 23일
1

JAVA

목록 보기
20/27

1. 예외 처리

1) 오류와 예외

  • 시스템 오류(error)
    • 가상 머신에서 발생, 프로그래머가 처리 할 수 없는 오류
    • 동적 메모리가 없는 경우, 스택 메모리 오버플로우등
  • 예외(Exception)
    • 프로그램에서 제어 할 수 있는 오류
    • 읽어들이려는 파일이 존재하지 않거나, 네트워크이나 DB연결이 안되는 경우 등
  • 자바는 안전성이 중요한 언어로
    대부분 프로그램에서 발생하는 오류에 대해 문법적으로 예외 처리를 해야함



2) 프로그램 오류

  • 컴파일 오류(compile error)
    • 프로그램 코드 작성 중 발생하는 문법적 오류
    • 최근에는 개발 환경(eclipse)에서 대부분의 컴파일 오류는 detection 됨
  • 실행 오류(runtime error)
    • 실행 중인 프로그램이 의도 하지 않은 동작(bug)을 하거나 프로그램이 중지 되는 오류
    • 비정상 종료가 되는 경우 시스템의 심각한 장애를 발생할 수 있음

👉 예외 처리가 필요한 이유



3) 예외 처리의 중요성

  • 프로그램의 비정상 종료를 피하여 시스템이 원할이 실행되도록 함
    → 시스템이 죽으면 안됨

but, 실행 오류가 발생한 경우 오류의 과정을 재현하는 것은 현실적으로 힘들다. . .

  • 오류가 발생한 경우 log를 남겨서
    추후 log 분석을 통해 그 원인을 파악하여 bug를 수정하는 것이 중요

👉 로그를 효율적으로 남기는 것을 고민!



2. 예외 클래스

모든 예외 클래스의 최상위 클래스는 Exception 클래스

예외 발생 상황

  • 자바에서는 다양한 예외들에 대해 그 처리를 위한 클래스가 제공되고 있음
예외예외 발생 상황
ClassNotFoundException존재하지 않는 클래스를 사용하려고 했을 때
IOException입/출력 작업 과정에서 문제가 발생했을 때
SQLException데이터베이스 연동 과정에서 문제가 발생했을 때
NumberFormatException숫자 형식이 아닌 데이터를 숫자로 변경하려고 했을 때
ClassCastException클래스에 대한 불가능한 타입변환을 시도하려고 했을 때
ArrayIndexOutOfBoundsException존재하지 않는 배열 공간을 사용하려고 했을 때
NullPointerException주소가 할당되지 않은 참조변수를 사용하려고 했을 때
ArithmeticException숫자를 0으로 나누는 등의 불가능한 산술연산을 수행할 때

  • Arithmetic Exception
    → 정수를 0 으로 나눈 경우 발생

  • NullPointerException
    → 초기화 되지 않은 Object를 사용하는 경우

  • ArrayIndexOutOfBoundsException
    → 배열의 크기를 넘어선 위치를 참조하려는 경우

  • FileNotFoundException
    → 참조하는 파일이 지정된 위치에 존재하지 않는 경우

  • ClassNotFoundException
    Class.forName(“sis.studentinfo.Student”); // 클래스가 로드되지 않은 경우

  • InterruptedException
    → Thread.sleep(), join(), Object의 wait()로
    non-runnable 상태인 thread를 Runnable하게 만들 수 있도록 사용할 수 있음



3. 예외 처리 하기

1) try-catch

  • try 블록에는 예외가 발생할 가능성이 있는 코드를 작성
    try 블록 안에서 예외가 발생하는 경우 catch 블록이 수행

  • 다중 catch 문도 사용 가능

  • trace 기능 : 아래 콘솔창에 찍히는 것

📌 예시 📌

  • 프로그래머가 예외를 처리해줘야 하는 예
  • 배열의 오류 처리
		int[] arr = {1,2,3,4,5};
		try{
			for(int i=0; i<=5; i++){
				System.out.println(arr[i]);
			}
		}catch(ArrayIndexOutOfBoundsException e){
			System.out.println(e);
		}
		System.out.println("비정상 종료되지 않았습니다.");

출력결과

비정상 종료되지 않았습니다.


2) try-catch-finally

  • finally 블럭에서 파일를 닫거나 네트웍을 닫는 등의 리소스 해제 구현을 함
  • try{} 블럭이 수행되는 경우에도
    finally{} 블럭은 항상 수행 됨
    catch블럭에 return이 있어도 수행됨
  • 여러 개의 예외 블럭이 있는 경우
    → 각각에서 리소스를 해제하지 않고 finally 블록에서 해제하도록 구현함

📌 예시 📌

  • 컴파일러에 의해 예외가 처리 되는 예
  • 파일 에러 처리
		FileInputStream fis = null;
		
		try {
			fis = new FileInputStream("a.txt");
			System.out.println("read");
			
		} catch (Exception e) {
			System.out.println(e);
			// return; // 예외발생해도 finally는 동작함
		
		} finally { // 항상 동작
			if(fis != null) {
				try {
					fis.close();
				} catch (Exception e) {
					e.printStackTrace();
				}	
			}
			System.out.println("finally");
		}
		System.out.println("end");

출력결과

만약 return; 이 있다면? end 제외 finally 만 출력



3) try-with-resources

  • 리소스를 사용하는 경우
    close() 하지 않아도 자동으로 해제 되도록 함
    • 자바 7부터 제공되는 구문
    • 리소스를 try() 내부에서 선언해야만 함
  • close()를 명시적으로 호출하지 않아도 try{}블록에서 열린 리소스는 ?
    → 정상적인 경우나 예외가 발생한 경우 모두 자동으로 해제됨
  • 해당 리소스 클래스가 AutoCloseable 인터페이스를 구현 해야 함
  • FileInputStream 의 경우에는 AutoCloseable 을 구현하고 있음
    • 자바 9 부터 리소스는 try() 외부에서 선언하고, 변수만을 try(obj) 와 같이 사용

📌 예시 📌

  • FileInputStream
		try(FileInputStream fis = new FileInputStream("a.txt")) {
			System.out.println("read");
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 자동으로 close() 메서드 호출
		System.out.println("end");
  • AutoCloseable 인터페이스 구현 실습
    • throw new Exception(); 예외 강제 생성(아래에서 자세하게 설명)
		AutoCloseableObj obj = new AutoCloseableObj();
		
		try(obj) {
			// 아무 코드 없어도 try블록 끝나면? 자동으로 AutoCloseable 
			// => AutoCloseableObj.java의 closing이 잘 출력됨
			
			throw new Exception(); // 예외 강제 생성후, catch문으로 이동함
			
		} catch (Exception e) {
			System.out.println("exception");
		
		}
		System.out.println("end");

4. 예외 처리 미루기

1) throws

예외 일괄 처리

  • , 예외 여러개 처리 가능
  • 여러 메소드에서 발생하는 예외를 특정 메소드로 집중
  • 예외가 발생할 수 있는 부분을 사용하는 문장에서 예외 처리 가능

📌 예시 📌

// loadClass() 메서드를 쓰는 쪽(main)에서 핸들링하도록 throws
	public Class loadClass(String fileName, String className) throws FileNotFoundException, ClassNotFoundException {
		FileInputStream fis = new FileInputStream(fileName);
		Class c = Class.forName(className);
		return c;
	}
	public static void main(String[] args) {

		ThrowsException test = new ThrowsException();
		try {
			test.loadClass("a.txt", "abc"); // "java.lang.String" 하면 loadClass() 메서드 잘 수행되었으므로 end만 출력

		} catch (FileNotFoundException e) { // 파일 없으면
			System.out.println(e);
		} catch (ClassNotFoundException e) { // 파일 있지만 클래스 없으면
			System.out.println(e);
		}
		System.out.println("end");
	}


2) throw 예약어

  • 원래, 시스템에서는 음수(-) 개념이 없음
    그러나, 사용자가 음수 입력 시 아무 문제가 발생하지 않을 때가 있음
  • 위처럼 강제적으로 예외 발생이 필요한 경우
    throw 를 사용하여 프로그램이 더 이상 진행되지 않도록 함

📌 예시 📌

throw new IllegalArgumentException();


5. 사용자 정의 예외

  • 자바에서 제공되는 예외 클래스외, 프로그래머가 직접 만들어야 하는 예외
  • 기존 예외 클래스 중 가장 유사한 예외 클래스에서 상속 받아 직접 만듦
  • 기본적으로 Exception 클래스를 상속해서 만들 수 있음
  • 사용자 정의 예외 클래스가
    Exception 클래스를 직접 상속 or RuntimeException 상속할지 결정

  • 보통 RuntimeException 을 상속하여 컴파일을 통과하는 예외로 만듦

📌 예시 📌

패스워드에 대한 예외 처리 하기

  • 패스워드 입력 시, 오류 처리 하는 경우
    • 비밀번호는 null일 수 없음
    • 비밀번호의 길이는 5이상
    • 비밀번호는 문자로만 이루어져서는 안됨(하나이상의 숫자나 특수문자를 포함)


  • 예외 처리 메서드
	public void setPassword(String password) throws PassWordException{
		if(password == null) {
			throw new PassWordException("비밀번호는 null일 수 없습니다");
		}
		
		else if(password.length() < 5) {
			throw new PassWordException("비밀번호는 5자 이상이어야 합니다");
		}
		else if(password.matches("[a-zA-Z]+")) { // 정규표현식
			throw new PassWordException("비밀번호는 숫자나 특수문자를 포함해야 합니다");
		}
		
		this.password = password;

	}
  • test main
	PasswordTest test = new PasswordTest();
		
		String password = null;
		try {
			test.setPassword(password);
			System.out.println("오류없음1");
		} catch (PassWordException e) {
			System.out.println(e.getMessage());
		}
		
		password = "abc";
		
		try {
			test.setPassword(password);
			System.out.println("오류없음2");
		} catch (PassWordException e) {
			System.out.println(e.getMessage());
		}
		
		password = "abcde";
		
		try {
			test.setPassword(password);
			System.out.println("오류없음3"); // 실행
		} catch (PassWordException e) {
			System.out.println(e.getMessage());
		}
		
		// set 실행
		password = "abcde1#";
		
		try {
			test.setPassword(password);
			System.out.println("오류없음4");
		} catch (PassWordException e) {
			System.out.println(e.getMessage());
		}
profile
imaginative and free developer. 백엔드 / UX / DATA / 기획에 관심있지만 고양이는 없는 예비 개발자👋

0개의 댓글