[자바] 예외 처리

Gammi·2022년 11월 3일
0

JAVA

목록 보기
24/35
post-thumbnail

🚫 예외


  • 개발자가 의도하지 않은 상황에서 발생하는 문제

  • 예외가 발생할 경우 프로그램이 비정상적으로 종료됨

    -> 예외 발생 위치의 아래쪽 코드 실행X


  • 오류와 달리 심각도 낮으며, 예외처리를 통해 비정상적인 종료 막을 수 있음

  • 예외 처리를 위해 try ~ catch 문 사용하여 처리

    -> 예외 발생 예상되는 코드들을 try 블록 내 기술

    -> 예외 발생 시 JVM에 의해 해당 예외 객체 전달받아 catch 블록 중 일치하는 타입에 대한 블록 실행하여 예외 처리

  • Exception 클래스 및 하위 클래스 사용하여 예외 처리


  • 두 가지 계열로 나누어짐

    -> 컴파일 시점에서 예외 발생 여부 체크 Compile Checked Exception

    • IOException, SQLException 등

    -> 실행 시점에서 예외 발생 여부 체크 Compile UnChecked Exception

    • ArrayIndexOfBoundsException, NullPointerException 등

< 예외 처리 기본 문법 >

try {
	// 예외 발생 예상되는 코드들...
} catch(예외클래스명1 변수명) {
	// 예외클래스명1에 해당하는 예외 발생 시 처리할 코드들...
} catch(예외클래스명n 변수명) {
	// 예외클래스명n에 해당하는 예외 발생 시 처리할 코드들...
} finally {
	// 예외 발생 여부와 관계없이 무조건 실행할 문장들...
    // DB 자원 반환, I/O 자원 반환 등
}





✔ finally 블록


  • 예외 발생 여부와 관계없이 무조건 수행해야할 문장 기술

  • return문을 만나서 메서드 종료하더라도 finally 블록 실행 후 호출한 곳으로 돌아감





✔ RuntimeException 클래스 계열들


나눗셈 연산의 피연산자가 0인 경우 ArithmeticException 예외 발생

⭐ 입력

System.out.println(3 / 0);

📌 출력

java.lang.ArithmeticException : / by zero
  • / by zero : 0에 의한 나눗셈으로 인해 예외가 발생했다는 메세지

배열에 존재하지 않는 인덱스 접근 시 ArrayIndexOutOfBoundsException 예외 발생

⭐ 입력

int[] arr = {1, 2, 3};
System.out.println(arr[5]);

📌 출력

java.lang.ArrayIndexOutOfBoundsException: Index 5
  • 인덱스 5번에서 문제 발생

객체의 주소를 참조하지 않는 참조변수(null) 접근 시 NullPointerException 예외 발생

⭐ 입력

String str = null;
System.out.println(str.length());

📌 출력

java.lang.NullPointerException

🔨 예외 처리


try {
    // 예외 발생 예상 코드 try 블록 내에 적어주기
    System.out.println(3 / 0);
    // 만약 여기서 예외가 발생했다면
    // 밑의 코드들은 실행되지 않고 바로 catch문으로 이동함
    int[] arr = {1, 2, 3};
    System.out.println(arr[5]);
  
    String str = null;
    System.out.println(str.length());
} catch(ArithmeticException e) {
  // 보통 변수명을 e로 많이 쓴댜
  // 여기에 예외 발생했을 때 처리할 코드 적어주기
  // 예외 발생하지 않으면 이 블록은 실행되지 않음
    e.printStackTract();
    // 예외 클래스, 발생위치, 원인 등을 자세히 출력
    System.out.println("0으로 나눌 수 없음" - e.getMessage());
    // 이 문장은 필수 아님
    // getMessage() 메서드 이용할 경우 예외 발생 원인 메세지를 문자열로 리턴해줌
} catch(ArrayIndexOutOfBoundsException e) {
    e.printStackTract();
} catch(NullPointerException e) {
    e.printStackTract();
} catch(Exception e) {
  // 위쪽의 catch 블록에서 지정되지 않은 나머지 예외 처리
  // 대신 예외 처리 방법 구분 못함
  // 반드시 다른 예외 클래스 다 기술한 뒤에 마지막에 적기!!!
    e.printStackTract();
} finally {
    // 무조건 실행될 문장들...
}





✔ 예외 처리의 위임(전달)


  • 예외 발생한 곳에서 try ~ catch 블록으로 직접 처리할 수 있지만 메서드 호출한 곳으로 예외 처리 위임도 가능

  • throws 키워드 사용

  • 예외 처리를 위임받은 메서드는 다시 예외 처리에 대한 책임이 발생하여 직접 처리하거나 또 다른 곳으로 위임 가능

  • 최종 단계의 메서드에서는 try ~ catch 블록을 사용하여 예외 직접 처리해야 함

  • throws 키워드 사용하여 지정하는 예외는 1개 또는 복수 개 지정 가능


< 예외 위임 기본 문법 >

  • 메서드 정의 시 메서드 선언부 마지막에 throws 키워드 쓰고 뒤에 예외를 위임할 클래스명을 기술(복수 개일 경우 콤마로 구분)

    [제한자] 리턴타입 메서드명([파라미터...]) throws 예외클래스명... {
    // 예외 발생 코드...
    }


public static void main(String[] args) {
// 메인메서드 
// 더 이상 도망갈 곳 없음...
// 여기서는 예외 위임X
// 무조건 처리해야만...
  try {
      A();
  } catch(Exception e) {
      e.printStackTrace();
  }
}

public static void A() throws Exception {
  B();
  // 예외를 위임받았으나!
  // 여기서도 위임을 하려고 한다면?
  // 여기서도 마찬가지로 throws 키워드를 사용해서
  // 두 예외 타입 모두 적어도 되지만
  // Exception 하나로 적어도 상관없음
  // 얘는 모든 예외 포함함
}

public static void B() throws RuntimeException, ClassNotFoundException {
  C();
  D();
  // 예외 위임 받았음
  // 직접 try ~ catch문 사용할 경우
  // try 블록 안에 C()와 D() 메서드 넣으면 됨
  
  // 근데 여기서도 A에게 위임하고자 한다면
  // 또 throws 키워드를 이용해서 위임해야 하는데
  // C에서 발생한 오류는 2개임
  // 얘네를 둘 다 적어줘도 되는데 상위 타입으로 결합해서 적는 것도 가능함!
}

public static void C() throws ArithmeticException, NullPointerException {
  System.out.println(3 / 0);
  // 오류 발생1
  String str = null;
  System.out.println(str.length());
  // 오류 발생2
  // 직접 try ~ catch 문으로 감싸거나 위임
}

public static void D() throws ClassNotFoundException {
  Class.forName("");
  System.out.println("D에서 오류 발생);
  // 직접 try ~ catch 블록 만들거나
  // 위임 가능함
}





✔ 사용자에 의한 예외 발생


  • 개발자 의도대로 예외를 직접 발생 시킬 수 있음

  • throw 키워드 사용하여 발생시킬 예외 클래스 객체 지정

    -> 예외 클래스 인스턴스 생성하여 강제로 해당 예외 발생시킴

  • 예외 클래스 인스턴스를 변수에 저장해서 발생시켜도 되지만 주로 일회성 예외를 발생시키므로 별도의 변수 없이 임시 객체 형태로 사용하는 경우 많음

    -> new 예외클래스명() 형태로 객체 생성하여 전달


    < 기본 문법 >

    예외를 발생시킬 코드 위치에서
    throw 예외객체;





✔ 사용자 정의 예외 클래스


  • 기존의 예외 클래스가 발생시킨 예외와 일치하지 않을 경우 Exception 클래스로 예외 처리 시 발생한 예외 파악하기 어려움

  • 예외 클래스를 작성하여 발생시킬 예외에 맞는 객체로 만들어 전달하면 예외 파악 쉬움

  • 사용자 정의 예외 클래스 정의 시 예외 클래스를 상속받아 정의

    -> 주로 Exception 클래스 상속받아 정의

  • 보통 생성자 정의하여 슈퍼클래스에 예외 메세지만 초기화


⭐ 입력

  public static void main(String[] args) {
    try {
        printScore(150);
    } catch(InvalidScoreException e) {
        e.printStackTrace();
    }
  }

  public static void printScore(int score) throws Exception {
  // 점수를 입력받아 학점을 계산하는 메서드
  // 점수 범위를 0 ~ 100 점 사이로 한정
  // 점수 범위를 벗어날 경우 오류 발생 필요함
  // 근데 벗어나도 int형 정수 범위에는 포함되니까 자바에서는 오류로 생각안함
  // 내가 직접 오류로 만들어야 함!!
    if(score < 0 || score > 100) {
      System.out.println(score + "점 : 점수 입력 오류");
      throw new Exception("점수 입력 오류 : " + score);
    }
    // throw 키워드 사용해서 해당 예외 클래스 객체를 생성
    // 하지만 점수 입력 오류에 대한 예외는 자바에 없기 때문에 Exception 클래스 사용함
    // 이렇게 자바에서 표시하는? 오류가 아니면 Exception 크래스 사용하면 됨
    // 예외 발생 시 표시할 메세지 생성자 파라미터로 전달
    // throw 뒤에 생성한 예외 객체의 참조변수 지정해서 해당 예외 발생시킴
    // throw e; 이런 식으로 해야 하는데
    // 나는 한 번만 쓰고 버릴 거라서 참조변수 안 쓰고
    // 바로 객체 생성했음(얘는 임시객체)
  }

  public static void userExceptionMethod(int score) throws  InvalidScoreException {
    if(score < 0 || score > 100) {
      throw new InvalidScoreException("점수 입력 오류 : " + score);
    }
    // Exception 클래스 대신 사용자 정의 예외클래스로 예외 발생 시키기
  }

class InvalidScoreException extends Exception {
// 사용자 정의 예외 클래스
// 클래스 이름은 상관 없음 원하는 걸로 아무거나...
// 주로 Exception 클래스 상속 받음
  public InvalidScoreException(String name) {
    // 생성자 정의해서 예외 메서지를 슈퍼클래스 생성자에 전달함
    super(message);
  }
}

📌 출력

ExceptionClass.InvalidScoreException: 점수 입력 오류 : 150
profile
개발자가 되었어요⭐️

0개의 댓글