Java

2024.04.29 JAVA 유용한 클래스 Exception(예외처리)

정훈5 2024. 4. 29. 08:52

Object

모든 클래스 최상위 클래스 이다.

메서드들이 존재

-- toString : 

-- equals() : 

-- hashcode() : 

-- clone() : 조사 

       --> 앝은 복사 : 주소만 복사

       --> 깊은 복사 : 객체 자체를 복사

-- String :  -->불편

-- StringBuffer 클래스 : 멀티 스레드 프로그램에 필요하다.

 

학습 목표 

1. 예외 처리에 대해서 알아 보자. 
2. 프로그램에서의 오류와 처리 방법
3. 상속을 활용한 사용자 정의 예외 클래스 만들기

 

예외 처리에 대해서 알아 보자.

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

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

package useful.ch03;

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]);
			} // end of for

		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("배열의 크기를 인덱스가 벗어 났습니다.");
			// System.out.println(e.getMessage() );

		}

		System.out.println("비정상 종료 되지 않았어요!");

		// ArrayIndexOutOfBoundsException t1;

	} // end of main

} // end of class

demon.txt 파일 만들기

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

package useful.ch03;

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

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

		FileInputStream fis = null;

		try {
			// fis = new FileInputStream("test1.txt"); // test1.txt 파일이 없다.
			fis = new FileInputStream("demo.txt"); // demo.txt 파일이 있다.
		} catch (FileNotFoundException e) {
			System.out.println("catch 구문 실행!!!");
			e.printStackTrace(); // 오류가 발생한 시점을 추적해 주는 기능
		}

		System.out.println("비정상 종료 되지 않았어요~");

	} // end of main

} // end of class

 

시나리오 코드 2-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;

		try {
			// fis = new FileInputStream("test1.txt"); // test1.txt 파일이 없다.
			fis = new FileInputStream("demo.txt"); // demo.txt 파일이 있다.
			// return; // : return 구문보다 강한 것 finally 이다.
			// return; // finally 까지만 출력한다. 뒤에 출력X
		} catch (FileNotFoundException e) {
			System.out.println("catch 구문 실행!!!");
			e.printStackTrace(); // 오류가 발생한 시점을 추적해 주는 기능
		} finally {
			// 반드시 수행 되어야 하는 코드 영역
			// 심지어 return 키워드를 만나더라도 여기는 수행이 된다.
			System.out.println("finally 블록 수행");
			// fis.close(); // 닫는 시점에 fis. <-- 객체가 생성 안되어 있을 수 있다.
			// fit.close(); // try -catch 사용이 된다.
			try {
				fis.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		System.out.println("비정상 종료 되지 않았어요~");

	} // end of main

} // end of class

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

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("자원 해제 완료");
		}

	}

}

시나리오 코드 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());
		}
	} // end of main

} // end of class

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

		return n1 / n2;
	} // end of divide()
} // end of class

 


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

package useful.ch03;
/*
 * 사용자 정의 예외 클래스 생성 IllegalAccessException
 * 
 */
public class PasswordException extends IllegalAccessException {
	
	public PasswordException(String message) {
		super(message);
	}

}


package useful.ch03;
/*
 * 사용자 정의 예외 클래스 생성 IllegalAccessException
 * 
 */
public class PasswordException extends RuntimeException {
	
	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자 이상이어야 합니다.");
		}
		// 정규 표현식을 활용할 수 있다. 
		// pwd <== a~z, A~Z  ==> true 
		// pwd <== a, 10, !  ==> false  
		if(pwd.matches("[a-zA-Z]+")) {
			throw new PasswordException("비밀번호는 숫자나 특수문자를 포함해야 합니다.");
		}
	}
}

 

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

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

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

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

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

정규식(Regular Expression, 줄여서 regex 또는 regexp)

문자열을 처리할 때 사용되는 강력한 도구로, 복잡한 검색, 매칭, 치환 작업을 간단하고 유연하게 수행할 수 있도록 돕습니다. 특정한 규칙을 가진 문자열의 집합을 표현하는데 사용되며, 이 규칙에 따라 문자열의 검색, 분할, 대체, 검증 등 다양한 작업을 자동화할 수 있습니다.

 

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

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

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

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

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

 

package useful.ch03;

public class NickNameException extends RuntimeException {
	// RuntimeException : 정상적인 작동 중에 발생할 수 있는 예외의 슈퍼 클래스
	
	public NickNameException(String message) {
		super(message);
	}
	
}
package useful.ch03;

public class NickName {

	String nick;

	public NickName() {
	}

	// get
	public String getNickname() {
		return nick;
	}

	// set
	// throws : 자신을 호출한 상위 메소드로 에러를 던지는 역할
	public void setNickname(String nick) throws NickNameException {

		if (nick == null) {
			// throw : 에러를 고의로 발생시킬 때 사용합니다.
			throw new NickNameException("닉네임은 공백으로 설정할 수 없습니다.");
		}

		if (nick.length() < 3) {
			// throw : 에러를 고의로 발생시킬 때 사용합니다.
			throw new NickNameException("닉네임은 3글자 미만으로 지정할 수 없습니다.");
		}

		if (nick.matches("[a-z A-Z+]")) {
			// throw : 에러를 고의로 발생시킬 때 사용합니다.
			throw new NickNameException("비밀번호는 숫자, 특수문자를 포함해야 합니다.");
		}

		this.nick = nick;
	}

}
package useful.ch03;

public class NickNameTest {

	public static void main(String[] args) {

		NickName nickname = new NickName();

		String inputNickname = null;
		inputNickname = "a3";
		try {
			nickname.setNickname(inputNickname);

		} catch (PasswordException e) {
			System.out.println("우리가 정의한 password 예외가 발생");
		} catch (Exception e) {
			System.out.println("예외 발생 : " + e.getMessage());
		}

	}

}