본문 바로가기

programming/Java [notion 정리본 업로드]

예외처리 (Exception)

A. 예외 🚨 Exception

A-1. 오류의 종류

  1. 시스템 에러 : Ex) 메모리 부족 (OOM - Out Of Memory)
    • 수정이 매우 힘들거나 불가능
    • 최적화나 성능 상향하는 방식으로 해결이 가능하기는 함
  2. 컴파일 에러
    • 문법 오류 ⇒ 반드시 수정
  3. 논리적인 오류
    • 프로그램이 정상적으로 컴파일되고 실행/종료가 되지만, 원하는 결과가 나오지 않는 경우
  4. 예외(exception) : 프로그램 실행 중에 발생할 수 있는 비정상적인 상황 → 반드시 수정
    1. if - else 문장
    2. try-catch 문장

A-2. 예외 종류 & 해결 방법

  1. 참조형 객체 NullPointerException
    public static void main(String[] args) {
    		// 예외종류 & 해결 방법
    		String s = null;
    
    		if (s != null) {
    			System.out.println("문자열 길이 : " + s.length());
    		} else {
    			System.out.println("null");
    		}
    
    	}+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    
  2. public static void main(String[] args) { // 예외종류 & 해결 방법 String s=null; System.out.println("문자열 길이 : " + s.length()); }
  3. 나누기 연산자를 사용할 때, 나누는 수가 0이면 ArithmeticException 발
    Exception in thread "main" java.lang.ArithmeticException: / by zero
    	at com.itwill.exception01.ExceptionMain01.main(ExceptionMain01.java:24)
    
    public static void main(String[] args) {
    		int x = 10;
    		int y = 0;
    
    		if (y != 0) {
    			System.out.println("몫 = " + (x / y));
    		} else {
    			System.out.println("0으로는 나눌 수 없습니다.");
    		}
    	}
    
  4. public static void main(String[] args) { int x = 10; int y = 0; System.out.println("몫 = " + (x / y)); }

B. 예외처리

B-1. try-catch-finally 구문

try {... 정상적인 상황에서 실행할 코드(블록) ...}  // 1
catch (Exception 타입 변수 선언) { ... 예외 발생 시 실행할 코드들 ... }  // 2
finally { ... 예외 발생 여부와 상관 없이 반드시 실행할 코드(블록)... }  // 3
  • 예외가 발생하지 않을 경우 : (1) ⇒ (3)
  • 예외가 발생하는 경우 : (1) ⇒ 예외발생 : 해당 코드에서 break; ⇒ (2) ⇒ (3)
    • try 내에 return 문장이 있더라도 finally 코드는 반드시 실행해야 함.
  • try-catch 문장에서 catch 블록은 1개 이상이 있어야 함.
  • finally 블록은 선택
  • catch 블록은 처리하려고 하는 예외 종류에 따라서 여러개를 작성할 수 있음.
    • catch 블록이 여러개 일 때는 하위 타입 에러들을 먼저 작성하고, 상위 타입의 에러들은 나중에 catch 해야 함.
  • finally block : 예외 발생 여부와 상관없이 항상 실행되는 블록
  • try 또는 catch 블록에 return 문장이 있어도, finally 블록이 실행된 후에 return 문장이 실행

🚨위에서 본 ArithmeticException을 try-catch구문으로 예외처리하기

public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);

		System.out.println("x = ");
		int x = Integer.parseInt(scanner.nextLine());

		System.out.println("y = ");
		int y = Integer.parseInt(scanner.nextLine());

		int result = x / y;

		System.out.println("result = " + result);
}
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at com.itwill.exception02.ExceptionMain02.main(ExceptionMain02.java:23)
  • 예외처리 구문
    • 위 구문에서 ArithmeticException 의 인스턴스인 경우만 catch하므로 다음과 같이 catch 구문을 더 넣어주는 방법이 있음.
public static void main(String[] args) { 
	Scanner scanner = new Scanner(System.in); 
    try { 
    	System.out.println("x = "); 
        int x = Integer.parseInt(scanner.nextLine()); 
        System.out.println("y = "); 
        int y = Integer.parseInt(scanner.nextLine()); 
        int result = x / y; 
        System.out.println("result = " + result); 
    } catch (ArithmeticException e) { 
    	System.out.println("y는 0이 될 수 없습니다."); 
    } catch (NumberFormatException e) { 
    	System.out.println("x와 y는 정수로만 입력해야 합니다."); 
    } 
}

사용자로부터 NumberFormatException 처리하기

package com.itwill.exception03;

import java.util.Scanner;

public class ExceptionMain {
	Scanner scanner = new Scanner(System.in);

	public ExceptionMain() {
		// TODO Auto-generated constructor stub
	}

	static ExceptionMain app = new ExceptionMain();

	public static void main(String[] args) {
		int num = app.inputInteger();

		System.out.println(num);
	}

	public int inputInteger() {
		int result = 0;

		while (true) {
			try {
				System.out.println("정수 입력 >> ");
				result = Integer.parseInt(scanner.nextLine());
				break;
			} catch (NumberFormatException e) {
				System.out.println(e.getClass());
			}
		}

		return result;
	}

public int inputInteger2() {
		try {
			int x = Integer.parseInt(scanner.nextLine());
			return x;
		} catch (Exception e) {
			System.out.println("정수를 입력하세요!");
			return inputInteger2();
		}
	}; // 재귀 함수 처리법

}

B-2. Multi-catch Block

  • Java 7 버전부터 하나의 catch 구문에서 여러 개의 Exception 클래스를 선언하고 예외를 처리
  • 문법
    • 여러 클래스 타입의 예외를 하나의 변수를 선언하여 사용할 수 있음
  • try { ... ; } catch (ExceptionClass1 | ExceptionClass2 | ... 변수 ) { ...; }
  • 🚨주의 : multi-catch 블록에서는 상속 관계가 있는 예외 클래스들을 함께 사용할 수 앖음!
  • 가능한 예
  • catch (NumberFormatException | ArithmeticException e) {...;}
  • 컴파일 에러 발생 예
  • catch (NumberFormatException | Exception e) {...;}
public static void main(String[] args) {

		try {
			int x = 100;
			int y = 7;
			System.out.println("몫 = " + (x + y));

			int[] arr = new int[0];

			arr[0] = 123;
			System.out.println(arr[0]);
		} catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
			System.out.println("message : " + e.getMessage());
		}
	}

B-3. 선언문에서 사용하는 throws/ 발생한 에러를 던지는 throw

package com.itwill.exception06;

public class Calculator {
	public int divide(int x, int y) throws Exception {
		if (y != 0)
			return x / y;
		// 메서드를 호출한 곳에 값을 반환

		throw new Exception("y는 0이될 수 없습니다.");
		// 메서드를 호출한 곳에 예외를 던짐.
	}
}
package com.itwill.exception06;

public class ExceptionMain06 {
	public static void main(String[] args) {
		// Calculator 타입 객체 생성
		Calculator calculator =new Calculator();
		
//		Calculator 타입 객체의 메서드 호출
		int result = calculator.divide(100, 8);
	}
}
  • throws Exception을 사용하여 선언한 메서드를 메인에서 호출할 때, 해당 메서드는 예외가 발생할 수 있으므로 위와 같이 컴파일 에러가 남.
  • Intelli J에서 이를 해결하기 위해 두 가지 대안을 주는데, Add throws declaration 과 Surround with try/catch 중 선택할 수 있음.
    • 하지만 throws 선언을 메인에서 하게 되면 에러가 발생하는 순간 프로그램이 비정상적 종료를 하게 되므로 이에 주의해서 try catch 구문을 사용하는 것이 일반적.
예외 클래스들의 상속 

예외 클래스들의 상속 관계 :

  • Object
    • Exception
      • RuntimeException, IOException, …
        • ArithmeticException, NullPointerException, NumberFormatException, …
  • throws 선언문이 있는 메서드들 중에서 RuntimeException과 그 하위 예외 클래스들을 던지는(throw) 메서드들은 try-catch를 사용하지 않아도 컴파일 가능.
  • RuntimeException이 아닌 예외를 던진다고 선언한 메서드들은 try-catch 구문이 필수가 아님

'programming > Java [notion 정리본 업로드]' 카테고리의 다른 글

JSP/SERVLET 프로젝트 생성 시 Dependencies  (0) 2024.04.13
Collection  (0) 2024.04.13
추상클래스와 인터페이스  (0) 2024.04.13
상속  (0) 2024.04.13
Class  (0) 2024.04.13