gi_dor

Java Exception 본문

Language/Java

Java Exception

기돌 2023. 11. 22. 18:37
728x90

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/package-tree.html

 

java.lang Class Hierarchy (Java SE 17 & JDK 17)

Class Hierarchy java.lang.Object java.lang.Boolean (implements java.lang.Comparable , java.lang.constant.Constable, java.io.Serializable) java.lang.Character (implements java.lang.Comparable , java.lang.constant.Constable, java.io.Serializable) java.lang.C

docs.oracle.com

 

🔸 예외처리

📌 프로그램 실행 시 발생할 수 있는 오류에 대비하는 것 , 프로그램 비정상 종료를 막고 실행상태를 유지한다

  • try - catch , try - catch - resource 블럭을 사용해서 예외처리하기
  • throws를 사용해 예외처리 떠넘기기
  • 일반적으로 예외처리는 한군데에서 일괄 처리
  • 자바에서는 main 메서드가있는 클래스에서 한다

 

🔸 오류의 종류

🔹 에러 Error

  • 시스템 , 운영체제 JVM의 잘못으로 발생
  • 개발자가 해결할 수 있는 문제가 아님
  • 예외처리 대상이 아님

🔹 예외 Exception

  • 개발자의 코딩실수 , 사용자의 잘못된 프로그램 사용 시 발생하는 오류
  • 예외처리를 통해 비정상적인 종료를 예방할 수 있다
  • 예외는 UncheckedException  , CheckedException 두 가지로 구분한다

🔹 UncheckedException

  • RuntimeException 클래스와 그 자식 클래스
  • 개발자의 코딩 실수로 발생
  • 컴파일러가 예외처리 여부를 체크하지 않음
    → 처리하지 않으면 런타임 중에 예외가 발생하여 프로그램이 비정상적으로 종료될 수 있음

주요 예외 클래스 
• Runtime Exception 
   → 모든 Unchecked Exception의 부모 클래스
• NullPointer Exception
   → 참조변수의 값이 null인 상태에서 필드나 메서드를 사용시 발생하는 예외 클래스
• ClassCast Exception
   → 클래스 형변환이 가능하지 않을 때 발생하는 예외 클래스
• Arithmetic Exception
   → 나눗셈에서 어떤 값을 0 으로 나눌 때 발생하는 예외 클래스
• IndexOutOfBoundsException
   → 배열 , 리스트 , 문자열에서 인덱스 범위를 벗어난 위치를 조회했을 때 발생하는 예외 클래스
• NumberFormatException
   → 숫자가 아닌 문자를 포함하고 있는 문자열을 정수나 실수로 변환할 때 발생하는 예외클래스
   Integer.paseInt() , Double.parseDouble() 등을 실행할 때 발생


 

🔹 CheckedException

  • Exception의 하위 클래스와 Exception클래스 에서 RuntimeException 클래스의 하위 클래스가 아닌 예외 클래스
  • 사용자의 잘못된 사용으로 인해 발생하는 오류
  • 컴파일러가 예외처리 구현 여부를 반드시 체크
    • 예외 처리 관련 코드가 구현되어 있지 않으면 컴파일 오류가 발생
    • 최신의 라이브러리나 프레임워크에서는 CheckedException의 사용비중이 줄어들고 있다

주요  클래스

• Exception
   → 모든 Checked Exception의 부모클래스
• ClassNotFoundException
   → 클래스 파일을 찾을 수 없을 때 발생하는 예외클래스
• IOException 
  → 읽기 / 쓰가 하는 도중 오류가 발행 했을 때 발생하는 예외클래스
  → 네트워크를 통해 다른 컴퓨터와 데이터 교환중 오류가 발생했을 때 발생하는 예외클래스
• FileNotFoundException
  → 파일을 찾을수 없을 때 발생하는 예외 클래스
• SQL Exception
  → 데이터 베이스 액세스 작업 중 오류가 발행했을 때 발생하는 예외클래스


🔹 예외 처리하기

  • try - catch구문으로 직접 예외 처리
  • throws를 사용해 예외처리 위임 - 책임 떠넘기기

FileWriter 생성자를 확인하면 처리되지 않은 예외 : java.io.IOException 이라고 명시되어있다
IOException은 CheckedException이며 예외처리가 필요하다

ctrl + 클릭을 통해  FileWriter에 throws IOException이 되어있는 것을 확인할 수 있다

이를 해결하기 위한 2가지 방법이 있다

  • 책임 떠넘기기
  • 예외처리 직접하기

1. 예외 처리를 메서드에 위임하기
→ 책임 떠넘기기 (알빠노 시전;;)

 

2. try - catch

◻ try - 예외 발생이 예상되는 수행문
◻ catch -  예외를 잡고 예외 발생 시 실행될 수행문 


🔹 예외 발생 시키기

  • 업무로직에 위배되는 상황이 발생하면 예외를 생성하고 던지자
  • throw new 예외클래스 (오류 메시지)
public class App1 {

    /**
     * 고객 등급과 주문금액을 전달받아서 적립포인트를 반환
     *
     * @param grade      등급
     * @param orderPrice 가격
     * @return 적립포인트 point 반환
     */

    public static int getPoint(String grade, int orderPrice) {
        Map<String, Double> map = new HashMap<String, Double>();
        map.put("gold", 0.05);
        map.put("silver", 0.03);
        map.put("bronze", 0.01);

        if (!map.containsKey(grade)) {
            throw new RuntimeException("[" + grade + "]가 비어있거나 유효한 고객등급이 아닙니다");
        }

        // 고객등급에 해당하는 적립률 조회하기
        double rate = map.get(grade);

        // 적립률과 주문금액을 이용해서  적립포인트 계산하기
        int point = (int) (orderPrice * rate);

        // 적립 포인트 반환
        return point;
    }

    public static void main(String[] args) {
        int point1 = getPoint("gold", 1000000);
        int point2 = getPoint("silver", 1000000);
        int point3 = getPoint("", 1000000);
    }

 


🔹 사용자 정의 예외 클래스

1. Checked사용자 정의 예외 클래스 - Exception 클래스를 상속받아서 정의한다

public class 사용자 정의 예외 extends Exception {
}

 

2. Unchecked 사용자정의 예외 클래스 - RuntimeException 클래스를 상속받아서 정의한다

📌 대부분의 사용저 정의 예외 클래스는 Unchecked Exception으로 정의한다

public class 사용자정의 예외 extends RuntimeException {
}

 


🔹 예외 클래스 주요  API

📌 Throwable

  • Error  , Exception의 부모클래스
  • 오류와 관련된 메서드들이 구현되어 있다
  • 모든 Error, Exception 클래스는 Throwable에 구현된 메서드를 상속받고 사용할 수 있다
  • 특별한 경우가 아니라면 사용자 정의 예외 클래스를 정의할 때 생성자만 정의해도 된다

생성자

public Throwable() { ... }
// 기본생성자

public Throwable(String message) { ... }
// 오류와 관련된 메세지를 전달받는 생성자

public Throwable(String message, Throwable cause) { ... }
// 오류와 관련된 메세지 및 오류의 원인이 되었던 이전 예외객체를 전달받는 생성자

public Throwable(Throwable cause) { ... }
// 오류의 원인이 되었던 이전 예외객체를 전달받는 생성자

 

메서드

Throwable getCouse()
// 오류발생의 원인이 되었던 오류를 반환

String getMessage()
// 오류와 관련된 상세한 메세지를 반환

void printStackTrace()
// 오류 발생과 관련되어서 실행되었던 코드를 화면에 출력
// 오류검출을 위한 디버깅 작업에서 참조한다.

void printStackTrace(PrintStream s)
// 오류 발생과 관련되어서 실행되었던 코드를 화면이 아닌 다른 곳에 출력하게 할 수 있다.

void printStackTrace(PrintWriter s)
// 오류 발생과 관련되어서 실행되었던 코드를 화면이 아닌 다른 곳에 출력하게 할 수 있다.

🔹 finally

  • try 블럭의 수행문이 정상 수행되던지 , 오류가 발생 하던지에 , 상관없이  반드시 실행해야하는 수행문을 포함한 블럭
  • Java7 부터 프로그램이 사용했던 자원을 자동으로 반납하는 기능이 추가되면서
    자원을 반납하기 위한 finally 블럭은 필요가 없어짐

일반적으로 데이터 베이스 엑세스 작업에는 외부 라이브러리 (myBatis , jpa)를 사용하게 되는데
이런 라이브러리들은 데이터베이스 작업과 관련된 자원 반납을 자동으로 처리해준다
이로인해 finally 블럭 사용할 필요 없다

try {
//  예외 발생이 예상되는 수행문
 } catch (예외 클래스 변수명) {
//  예외 발생시 실행할 수행문
 } finally {
//	정상실행 혹은 예외 발생 했거나 상관없이 무조건 실해외어야하는 수행문
}

 

 


🔹 예외의 변환

  • 메서드에서 발생하는 예외를 잡고 - catch , 대신 다른 예외를 발생 시키는것
  • 예외를 일괄로 처리하는 곳에서 처리할 예외의 종류를 줄일 수 있다.

메서드에서 발생하는 다양한 예외를 일괄처리하는 곳으로 throws로 위임하는 대신
사용자 정의 예외를 대신 발생 시킴으로써 , 일괄처리 대상 예외를 
사용자 정의 예외로 한정시킨다

// FileNotFoundException, IOException 

public static String readfile() throws FileNotFoundException, IOException {	
	BufferedReader reader = new BufferedReader(new FileReader("sample.txt"));
	String text = reader.readLine();
			
	return text;
	
}

// ParseException
public static Date toDate(String text) throws ParseException {
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
	Date date = sdf.parse(text);
	return date
}

// HtaException
public static void signIn(User user) {
	User savedUser = userRepo.findById(user.getId());
	if (savedUser != null) {
		throw new HtaException("["+user.getId()+"]는 이미 사용중이 아이디입니다.");
	}
}

public static void main(String[] args) {
	try {
		readfile();
		toDate("2120-11-21");
		signIn(new User("hong", "zxcv1234", "홍길동"));

	} catch (FileNotFoundException ex) {

	} catch (IOException ex) {

	} catch (ParseException ex) {

	} catch (HtaException ex) {

	} catch (Exception ex) {

	}	
}


// HtaException  발생
public static String readfile() {
	try {	
		BufferedReader reader = new BufferedReader(new FileReader("sample.txt"));
		String text = reader.readLine();
			
		return text;
	} catch (FileNotfoundException ex) {
		throw new HtaException("sample.txt", ex);
	} catch (IOException ex) {
		throw new HtaException(ex);
	}
	
}


// HtaException
public static Date toDate(String text) {
	try {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Date date = sdf.parse(text);
		return date
	} catch (ParseException ex) {
		throw new HtaException(text, ex);
	}
}
// HtaException
public static void signIn(User user) {
	User savedUser = userRepo.findById(user.getId());
	if (savedUser != null) {
		throw new HtaException("["+user.getId()+"]는 이미 사용중이 아이디입니다.");
	}
}
	
public static void main(String[] args) {
	try {
		readfile();
		toDate("2120-11-21");
		signIn(new User("hong", "zxcv1234", "홍길동"));

	} catch (HtaException ex) {

	} catch (Exception ex) {

	}	
}

 


🔹 예외 처리 이렇게 하자

// 예외처리를 하지 않음
public static void main(String[] args) throws Exception {
	method1();	
	method1();
	method1();

}

public void refadfile(String filename) throws FileNotFoundException, IOException {
	// FileNotFoundException 발생
	BufferdReader br = new new BufferdReader(new FileReader(filename));
	// IOException 발생
	String text = br.readLine();

	return text;

}

public void refadfile(String filename) throws IOException {
	// FileNotFoundException 발생
	BufferdReader br = new new BufferdReader(new FileReader(filename));
	// IOException 발생
	String text = br.readLine();

	return text;

}

public void refadfile(String filename) throws Exception {
	// FileNotFoundException 발생
	BufferdReader br = new new BufferdReader(new FileReader(filename));
	// IOException 발생
	String text = br.readLine();

	return text;

}

// 예외가 발생했을 때도 값이 반환되게 하자
public int method(String text) {
	try {
		int number = Interger.parseInt(text);
		return number;
	} catch (예외  e)
		return 0;
	}
}
	
// 예외가 발생했을 때, 값을 반환하는 대신 예외를 던지자
public int method(String text)
	try {
		int number = Interger.parseInt(text);
		return number;
	} catch (예외  e)
		throw e;
	}

 

 

 

🔸 예외처리 일반적인 형태

 

// 1. 예외처리를 일괄처리하는 곳으로 위임
public void method() throws 예외 {
	수행문;	// 예외발생
    }
    
// 2. 예외를 사용자 정의 예외로 변환해서 일괄처리하는곳으 보낸다
public void method() {
	try { 
    	수행문; // 예외발생
         } catch (예외 ex) {
         	throw new HtaException(ex);
         }
 }
 
// 3. 업무로직에 위배되는 상화잉 발생하면 예외를 강제 발생
public void method() {
	if (업무로직에 위배된다면 ) {
    	throw new Exception(메세지);
        }
     }
     
     
  // catch 로 예외를 잡아만 두고 던지지 않음 
  // 메서드에서 발생한 예외를 일괄처리하는 곳으로 보내지 않는다.
  
  
  // 최악의 예외처리 코드
  // 오류에대한 메세지만 출력될듯 ?
public void method () {
	try {	
    	수행문;	// 예외발생
         } catch ( 예외 ex ) {
          	ex.printStackTrace();
         }
      }

 

 

728x90

'Language > Java' 카테고리의 다른 글

Java 프로세스와 스레드  (1) 2023.11.29
Java I / O  (0) 2023.11.23
Java 제네릭, 컬렉션 , Set , List , Map , Stack  (1) 2023.11.20
Java Iterator , Score CRUD  (1) 2023.11.17
Java Random , Math  (0) 2023.11.16