예외 처리
자바 프로그래밍에서의 예외 처리(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 |