Java

Exception(예외처리)

ryeonng 2024. 4. 30. 15:30

예외 처리

자바 프로그래밍에서의 예외 처리(Exception Handling)는 프로그램 실행 중 발생할 수 있는 예상치 못한 상황(예외)을 관리하는 방법이다.
예외 처리를 통해 프로그램의 비정상적인 종료를 막고, 예외 상황을 보다 적절하게 처리하여 프로그램의 안정성과 신뢰성을 높일 수 있다.

 

 

자바에서는 다음과 같은 방법으로 예외를 처리합니다

 

try {
    // 예외가 발생할 수 있는 코드
} catch (ExceptionType1 e) {
    // ExceptionType1 예외를 처리하는 코드
} catch (ExceptionType2 e) {
    // ExceptionType2 예외를 처리하는 코드
}

 

try {
    // 예외가 발생할 수 있는 코드
} catch (Exception e) {
    // 예외 처리 코드
} finally {
    // 항상 실행되는 코드
}

finally 블록 : try 블록의 실행 여부와 관계없이 항상 실행되어야 하는 코드(예: 자원 해제 로직)를 포함한다.

finally 블록은 모든 catch 블록 다음에 온다.

 

if (someCondition) {
    throw new Exception("Custom Error Message");
}

----------------------------------------------------------------

public void someMethod() throws IOException, NullPointerException {
    // 예외가 발생할 수 있는 코드
}

 


프로그램에서의 오류와 예외처리 방법

 

● 컴파일 오류(compile error)

프로그램 코드 작성 중 발생하는 문법적 오류

최근에는 개발 환경(eclipse)에서 대부분의 컴파일 오류는 detection 됨.

 

● 실행 오류(runtime error)

실행 중인 프로그램이 의도 하지 않은 동작(bug)을 하거나 프로그램이 중지 되는 오류

실행 오류는 비정상 종료가 되는 경우 시스템의 심각한 장애를 일으킨다.

 

예외 처리의 중요성

  • 프로그램의 비정상적인 종료를 피하여 시스템이 원할하게 실행되도록 함
  • 실행 오류가 발생한 경우 오류의 과정을 재현하는 것은 현실적으로 힘들다.
  • 오류가 발생한 경우 log를 남겨서 추후 log 분석을 통해 그 원인을 파악하여 bug를 수정하는 것이 중요

 

오류와 예외 클래스

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

 

 

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

 


 

시나리오 코드 1 ( try - catch 문 ) 

 

package useful.ch03;

import java.util.Iterator;

public class ArrayExceptionHandling {

	// 메인 쓰레드
	public static void main(String[] args) {

		// 런타임 에러
		int[] arr = {1,2,3,4,5};
		
		try {
			// 예외가 발생할 수 있는 코드를 넣어서 수행 시킨다.
			for (int i = 0; i < 10; i++) {
				System.out.println(arr[i]);
			}
		} catch(ArrayIndexOutOfBoundsException e) {
			System.out.println("배열의 크기를 인덱스가 벗어났습니다.");
			//System.out.println(e.getMessage());
		}
		
		System.out.println("비정상 종료 되지 않았습니다.");
		
		//ArrayIndexOutOfBoundsException t1;

		
	} // end of main

} // end of class

: 실행 오류 ( runtime error )가 발생할 가능성이 있는 코드에 예외 처리를 할 수 있다.

 


시나리오 코드 2 ( try - catch - finally 문 ) 

package useful.ch03;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileExceptionHandling {

	// 메인 쓰레드
	public static void main(String[] args) {

		FileInputStream fis = null;
		
//		fis = new FileInputStream("test1.txt"); // FileNotFoundException : txt파일이 없을 수 있다. F2 예외처리 
		try {
			fis = new FileInputStream("demo.txt");
			//return; // catch구문은 실행 x finally구문만 실행
		} catch (FileNotFoundException e) {
			System.out.println("catch 구문 실행");
			e.printStackTrace(); 
		} finally {
			// 반드시 수행 되어야 하는 코드 영역
			// 심지어 return 키워드를 만나더라도 수행이 된다.
			System.out.println("finally 블록 수행");
			
//			fis.close(); // 닫는 시점에 fis. <- 객체가 생성이 안되었을 경우도 존재 함.F2 예외처리
			try {
				fis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		System.out.println("비정상 - 종료 되지 않았습니다.");
		
	} // end of main

} // end of class

 

package useful.ch03;

import java.util.Scanner;

public class FinallyHandling {

	public static void main(String[] args) {

		// try-catch-finally
		// 언제 finally를 사용해야 할까?
		// → 자원을 반드시 닫아 주어야 할 때 등등
		Scanner scanner = new Scanner(System.in);

		try {
			int result = scanner.nextInt();
			System.out.println("result :" + result);
			// scanner의 자원을 다 사용 했다면 자원을 해제해야 한다.
		} finally {
			scanner.close();
			System.out.println("자원 해제 완료");
		}
		
		
	} // end of main

} // end of class

: 예외가 발생 하더라도 finally 블록을 실행해서 자원을 닫을 수 있다.

 


시나리오 코드 3 ( throws 예외 처리 던지기 (미루기) )

 

package useful.ch03;

public class ThrowsHandling {

	// 메인 쓰레드
	public static void main(String[] args) {

		Calc calc = new Calc();
		
		try {
			// 던져서 강제성이 발생되고,
			// 사용하는 사람이 직접 예외 처리 핸들링을 할 수 있다.
			calc.divide(10, 0);
		} catch (ArithmeticException e) {
			System.out.println("어떤 수를 0으로 나눌 수 없습니다.");
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		
		Exception exception;
		
	} // end of main

} // end of class

class Calc {
	
	public int divide(int n1, int n2) throws Exception {
		// 사용자가 0을 입력하면 예외가 발생 될 수 있는 코드 영역이다.
		// * 해결 방법
		// 1. 해당 메서드에서 직접 예외 처리를 구현한다.
		// 2. 사용하는 사람이 직접 예외처리를 할 수 있도록 던져 버린다.
		return n1 / n2;
	}
	
}

 


시나리오 코드 4 ( 사용자 정의 예외 클래스 )

 

package useful.ch03;
/**
 * 사용자 정의 예외 클래스 생성
 */
// 상속으로 예외 클래스 처리
public class PasswordException extends IllegalArgumentException {

	public PasswordException(String message) {
		super(message);
	}
	
}

 

package useful.ch03;

public class Password {
	
	private String pwd;
	
	// getter 
	public String getPwd() {
		return pwd;
	}
	
	// setter
	public void setPwd(String pwd) throws PasswordException {
		
		if(pwd == null) {
			throw new PasswordException("비밀번호는 null 값일 수 없습니다.");
		}
		
		if(pwd.length() < 5) {
			throw new PasswordException("비밀번호는 5자 이상이어야 합니다.");
		}
		
		// matches로 정규 표현식을 활용할 수 있다.
		// pwd <== a~z , A~Z ==> true
		// pwd <== a, 10, ! ==> flase
		if(pwd.matches("[a-zA-Z]+")) {	
			throw new PasswordException("비밀번호는 숫자나 특수문자를 포함해야 합니다.");
		}
	}

}

 

package useful.ch03;

public class Password {

	private String pwd;

	// getter
	public String getPwd() {
		return pwd;
	}

	// setter
	public void setPwd(String pwd) throws PasswordException {

		if (pwd == null) {
			throw new PasswordException("비밀번호는 null 값일 수 없습니다.");
		}

		if (pwd.length() < 5) {
			throw new PasswordException("비밀번호는 5자 이상이어야 합니다.");
		}

		// matches로 정규 표현식을 활용할 수 있다.
		// pwd <== a~z , A~Z ==> true
		// pwd <== a, 10, ! ==> flase
		if (pwd.matches("[a-zA-Z]+")) {
			throw new PasswordException("비밀번호는 숫자나 특수문자를 포함해야 합니다.");
		}

		// [...] : 대괄호는 문자열을 나타낸다.
		// a-z, A-Z : 모든 알파벳 문자열을 말한다.
		// + : 바로 앞에 표현식이 하나 이상은 반복되어야 한다.
		// 즉, "Hello" 라고 쓰면, true를 반환한다.
		// "A1", "bbb"(3자 미만이므로) --> false 를 반환한다.
		this.pwd = pwd;

	}
}

 

package useful.ch03;

public class PasswordMainTest {

	public static void main(String[] args) {

		Password password = new Password();
		
		String inputpwd = null;
		inputpwd = "ab";
		
		// 테스트 해보니 아래 코드는 실행 시점에 예외가 발생되는 코드네?
		// * 해결방법
		// 1. 직접 예외 처리
		// 2. 던지기
		
		try {
			password.setPwd(inputpwd);
		} catch (PasswordException e) {
			System.out.println("우리가 정의한 password 예외가 발생");
		} catch (Exception e) {
			System.out.println("예외 발생 :" + e.getMessage());
		}
		
	} // end of main
	
} // end of class

 


 

문제 예시 - 사용자 정의 클래스의 활용

 

사용자 정의 예외 클래스 만드는 법 

1. 클래스를 설계 ---> 상속을 받아야 한다. 
2. 활용할 수 있는 클래스에서 throws와 throw 를 활용 
2 - 1 : Password 클래스에 활용 
3. 코드 실행 시점에서 테스트 및 예외 처리 작성 

-----------------------------------------------------

NickName 클래스를 설계 
-- String nick; 
-- get
-- set -> 예외를 던지는 코드를 추가하세요  
NickNameException 상속 --> RuntimeExcption 
NickNameTest 클래스로 확인 하기

 

'Java' 카테고리의 다른 글

자바 Thread  (0) 2024.05.02
Swing (이미지 겹치기)  (0) 2024.05.02
String, StringBuffer 클래스  (1) 2024.04.29
Object 클래스  (0) 2024.04.29
인터페이스(interface)  (1) 2024.04.25