자바 - Exception ( 예외 처리 )

빵제이·2023년 8월 1일
0

자바

목록 보기
35/37

[ Exception (예외 처리) ]

  • 예외 처리는 코드 작성자가 예기치 않게 발생하는 에러들에 대응할 수 도록 사전에 방지하는 것이다.
  • 예외 처리를 하면 프로그램의 비정상적인 종료를 방지하여 정상적인 실행 상태를 유지할 수 있다.

< 프로그램에서 에러가 발생하는 이유 >

  • 에러가 발생하는 원인은 수없이 다양하다.
    하지만 자주 발생하는 에러의 몇 가지 예시는 다음과 같다.

  • 사용자의 입력 실수

  • 네트워크 연결 끊김

  • 메모리 공간 부족

  • 개발자의 코드 실수

  • 유효하지 않는 파일 사용

즉, 에러가 발생하는 원인은 크게 내부적인 요인과 외부적인 요인이 있다.

외부적인 요인에는 입력 에러, 하드웨어 문제, 네트워크 연결 에러 등이 있으며, 내부적인 요인으로는 개발자의 코드 작성에 있다.


< 에러와 예외 (Error and Exception) >

  • 에러(Error)의 경우, 한 번 발생하면 복구하기 어려운 수준의 심각한 문제를 의미하고,
    대표적으로 메모리 부족인 OutOfMemoryError와 스택 오버플로우(StackOverflowError)가 있다.

  • 예외(Exception)는 개발자의 잘못된 사용으로 인해 발생하는 에러는 상대적으로 약한 문제의 수준을 말한다. 즉, 개발자의 실수로 인해 발생하는 것이다.
    (이는 코드 수정을 통해 수습이 가능한 문제이다.)

출처) https://ittrue.tistory.com/140
(글 작성자가 공부를 위해 위 주소에서 '개념 부분'만 퍼왔음을 알립니다.)


< try - catch >

[ ex01 ]

public static void ex01() {
   
	try {
     String name = "tom";
     Integer.parseInt(name); // 발생한 NumberFormatException을 catch 블록으로 던진	다.(throw라고 부름)
   } catch(NumberFormatException e) {  // RuntimeException, Exception 가능
     //예외 객체 이름은 일반적으로 'e'로 부름.
     System.out.println("예외발생");
   }
 }

[ ex02 ]

public static void ex02() {
    
	try {
      // Scanner 는 import 필수.
      Scanner sc = new Scanner(System.in);
      System.out.println("덧셈식을 입력하세요(예 : 1+2)");
      String expr = sc.next();              // split은 배열로 만들어줌.
      String[] numbers = expr.split("[+]"); // numbers = {"1", "2"}    // 대괄호[] 를 써주면 정규식이 아닌 문자로 인식한다. 
      int number1 = Integer.parseInt(numbers[0]);
      int number2 = Integer.parseInt(numbers[1]);
      System.out.println(number1 + number2);
      sc.close();
    } catch(NumberFormatException e) {
      System.out.println("정수 연산만 가능합니다.");
    } catch(ArrayIndexOutOfBoundsException e) {
      System.out.println("덧셈식에 +를 포함해서 입력하세요.");
    } catch(Exception e) {  // NumberFormatException 과 ArrayIndexOutOfBoundsException 으로 처리못하는 예외를 마지막 Exception이 담당한다.
      System.out.println("알 수 없는 예외가 발생했습니다.");
    }
      // catch 여러 개 만드는 이유는 사용자에게 안내하기 위해서이다.
  }

[ ex03 ]

 public static void ex03() {
    
	// 반드시 try - catch가 필요한 예외를 Checked Exception이라고 한다.
    
    try {
      URL url = new URL("https://www.naver.com");
  } catch(Exception e) {
    System.out.println("예외 발생");
  // 예외 종류를 공부하는 건 쓸데없음 ( 다 Exception 으로 받으면 됨 )
    }
  }
  public static void main(String[] args) {
    ex02();
  }

< finally >

  • finally 블록
    1. try-catch문의 마지막 블록으로 추가할 수 있다. (생략 가능)
    1. 예외 발생 여부와 상관 없이 "항상 마지막"에 실행된다.

[ 메인 메소드 ]

public static void main(String[] args) {
   
	// 나이를 입력 받아서 "주류 구매 가능", "주류 구매 불가능" 출력하기
   // 예외 처리
   
	// try 블록과 finally 블록에서 모두 사용할 수 있도록 scope 조정.
   Scanner sc = null;   // 선언과 생성만 위 아래로 분리.
                        // 객체들의 초기값은 null.
 try {
   sc = new Scanner(System.in);
   System.out.println("몇 살이세요?");
   int age = sc.nextInt();   // 정수 입력 받는 것 : nextInt()
   System.out.println(age >= 20 ? "주류 구매 가능" : "주류 구매 불가능");

 } catch(Exception e) {
   System.out.println("잘 모르겠어요.");
 } finally {
   sc.close();
   }
   // finally는 주로 자원 반납용으로 사용한다.
   // close 는 항상 finally에 써준다.
   // scope : 범위 / sc가 선언된 스코프는 try 블록이다. try 블록을 벗어나면 사용 못함.
   // 선언한 곳 { } 에서만 사용할 수 있다. 
 } 

< throw >

    1. 예외 객체를 직접 생성(new) 해서 던질 때 사용한다.
    1. Java는 예외로 판단하지 않는 것들을 던질 때 사용한다.
    1. 개발자가 직접 예외를 처리할 때 사용한다.

[ 메인 메소드 ]

public static void main(String[] args) {
   
	Scanner sc = null;  
   try {
     sc = new Scanner(System.in);
     System.out.println("몇 살이세요?");
     int age = sc.nextInt();   
     if(age < 0 || age > 100) {
       throw new RuntimeException(); // 직접 RuntimeException을 발생시켜서 던진다.
     }
     System.out.println(age >= 20 ? "주류 구매 가능" : "주류 구매 불가능");

	} catch(Exception e) {
     System.out.println("잘 모르겠어요.");
   } finally {
     sc.close();
   }
	}

< catch >

[ ex01 ]

public static void ex01() {
    
	try {
      
	// 1. Java가 발생시킨 예외
      // int a = 5 / 0;
      // System.out.println(a);
      
	// 2. 개발자가 발생시킨 예외
      throw new RuntimeException("개발자 예외");
      
	} catch (Exception e) {
      
	// 예외 클래스 확인하기
      System.out.println(e.getClass().getName()); // Object의 메소드 활용
      
	// 예외 메시지 확인하기(예외가 발생한 이유)
      System.out.println(e.getMessage());    
	}  
}

[ ex02 ]

public static void ex02(String name) {
   
// 예외처리 : try {} catch(Exception e) { e.printStackTrace(); }
   try {
     System.out.println(name.substring(0, 1));
   } catch(Exception e) {
     e.printStackTrace();  //예외 추적 메시지를 출력하는 메소드 (개발 중에는 이것만 사용한다.)
   } 
 }

 public static void main(String[] args) {
   ex02(null);
 }

< throws >

    1. 메소드에서 발생하는 모든 예외를 던질 때 사용한다.
    1. 메소드 내부에서 try-catch를 처리하지 않고, 메소드를 호출하는 곳으로 예외를 던질 때 사용한다.
    1. 메소드를 호출하는 곳에서 try-catch를 처리한다.
  // print 메소드 정의
  // throws NullPointerException : 메소드를 호출할 때 NullPointerException 처리가 필요하다.
   
  public static void print(String str) throws NullPointerException {
  
	System.out.println("첫 글자: " + str.substring(0, 1)); // 0번인덱스 부터 ~ 1번인덱스 전까지.
    System.out.println("나머지 글자: " + str.substring(1)); // 인덱스가 하나면 끝까지 전부 출력.
	 }

[ 메인 메소드 ]

public static void main(String[] args) {
  
	try {
   // print 메소드 호출
   print("홍길동");
   print(null);
   } catch (NullPointerException e) {
    System.out.println(e.getMessage());
   }
 }
profile
개인 아카이브

1개의 댓글

comment-user-thumbnail
2023년 8월 1일

정리가 잘 된 글이네요. 도움이 됐습니다.

답글 달기