9주차 과제 : 예외 처리

Lee·2021년 1월 15일
0
post-thumbnail

예외처리

자바에서 제공하는 예외처리에 대해 공부해보자 📖

  • 자바에서 예외 처리 방법 (try, catch, throw, throws, finally)
  • 자바가 제공하는 예외 계층 구조
  • Exception과 Error의 차이는?
  • RuntimeException과 RE가 아닌 것의 차이는?
  • 커스텀한 예외 만드는 방법

지난 8주차 과제 회고 ✍️

자바 8 이후에 인터페이스와 추상클래스가 하는 역할이 동일하다고 생각하여 질문하게 되었고, 그에 따른 선장님의 대답은

과연 인터페이스에서 다 구현할 수 있을까?
추상 클래스도 하나의 클래스이기 때문에 상태 정보를 저장할 수 있지만, 인터페이스는 저장할 수 없다.

이 대답을 듣고 단 1초만에 생각이 바뀌었다..👍

프로그램 오류 📌

프로그램이 실행 중 어떤 원인에서 의해서 오작동을 하거나 비정상적으로 종료되는 경우가 있다. 이러한 결과를 초래하는 원인을 프로그램 에러 또는 오류라고 한다. 발생하는 시점에 따라 컴파일 에러(compile-time-error)런타임 에러(runtime error)로 나눌 수 있는데, 말 그대로 컴파일 에러(compile-time-error)는 컴파일 할 때 발생하는 에러이고, 프로그램이 실행 도중에 발생하는 에러를 런타임 에러(runtime error)라고 한다.

에러, 예외 ⭐️

자바에서 프로그램 실행 시(runtime) 발생할 수 있는 프로그램 오류를 에러(error)예외(exception) 이 두 가지로 구분한다. 에러는 개발자가 작성한 자바 프로그램이 동작하는 환경에서 문제가 발생한 것을 의미한다 예를 들어 메모리가 부족하다던가 운영체제 상에 문제가 있는 것처럼 개발자 스스로가 발생시킨 원인이 아닌 어쩔 수 없이 돌아가는 환경에 의해서 발생하는 문제를 에러라고 한다, 반면에 예외는 개발자가 의도한 대로 작성한 코드가 다른 상황에서 직면하는 것을 예외라고 한다. 예를 들면 파일을 읽어서 문자열 가져온다는 코드를 작성했을 때 파일을 읽어오는 과정에서 개발자는 파일이 있다고 가정하에 코드를 작성했는데 파일이 없는 경우, 혹은 배열에서 인덱스 값을 잘못 참조할 경우이다.

  • 에러(error) - 프로그램 코드에 의해서 수습될 수 없는 오류
  • 예외(exception) - 프로그램 코드에 의해서 수습될 수 있는 오류

예외처리란? 🤔

위에서 언급했듯이 프로그램이 실행 도중 비정상적으로 종료되는 에러는 어쩔 수 없지만, 예외는 개발자가 이에 대한 예방책? 을 미리 마련할 수 있다. 프로그램 실행 시 발생할 수 있는 예외적인 상황 발생에 대한 대비를 코드로 작성하는 것이다. 이렇게 개발자가 예외처리를 하는 목적은 예외의 발생으로 인한 프로그램에 갑작스런 종료를 막고, 정상적인 상태를 유지시키기 위함이다.

예외적인 상황? 🤔

public class ExceptionTest {

    private String str; // 값을 초기화 하지 않은 상태 (null)

    public String getStr() {
        return str;
    }

    public static void main(String[] args) {
        ExceptionTest exceptionTest = new ExceptionTest();
        
        // str 값이 null인 상황에서 "test"라는 문자열을 비교하는 과정에서 예외 발생
        if (exceptionTest.getStr().equals("test")) { 
            System.out.println(exceptionTest.getStr());
        }
    }
}
Exception in thread "main" java.lang.NullPointerException
	at ExceptionTest.main(ExceptionTest.java:12)

예외처리 하기 🚀

자바에선 예외처리를 하기 위해 try/catch/finally 구문을 제공한다.

try -> 예외가 발생하는 코드를 작성
catch -> 예외가 발생했을 때 처리 코드 작성
finally -> 반드시 실행되어야 하는 구문 작성

  • try-catch
public class ExceptionTest {

    private String str;

    public String getStr() {
        return str;
    }

    public static void main(String[] args) {
        ExceptionTest exceptionTest = new ExceptionTest();

        try { 
          // try 구문안에 에러가 발생할 것 같은 코드를 작성하여 넣어준다.
            if (exceptionTest.getStr().equals("test")) { 
                System.out.println(exceptionTest.getStr());
            }
        } catch (NullPointerException e) { 
          // NullPointerException이 발생했을 경우, 처리 로직이 들어간다.
          // 이때 catch구문에 매개변수 타입은 try문에서 발생하는 예외 타입으로 선언되어야 한다.
            System.out.println("해당 str이 null 입니다.");
        }
    }
}
해당 str이 null 입니다.

Process finished with exit code 0
  • 중첩 try-catch
public class ExceptionTest {

    private String str;

    public String getStr() {
        return str;
    }

    public static void main(String[] args) {
        ExceptionTest exceptionTest = new ExceptionTest();
        int[] arrays = {10, 20, 30};

      // try문에 안에 또 다른 try문을 만났을 때 실행순서가 궁금해서 구간별로 Exception을 만들어보았다.
      // 다중 for문과 마찬가지로 바깥쪽 try문 안에 실행구문과 안쪽 try문의 작성된 위치에 따라 출력순서만 조금 다를뿐 바깥 try문이 먼저 실행되고, 안쪽 try문이 실행된다. 
        try {
            System.out.println("outer try");
            try {
                System.out.println("inner try");
                System.out.println(arrays[3]);
            } catch (ArrayIndexOutOfBoundsException e) {
                System.out.println("inner catch");
            }
            if (exceptionTest.getStr().equals("test")) {
                System.out.println("outer try");
            }
        } catch (NullPointerException e) {
            System.out.println("outer catch");
        }
    }
}
outer try
inner try
inner catch
outer catch
  • 다중 try-catch
public class Test {
    public static void main(String[] args) {

        String str = null;
        int[] scores = {10,20,30};
        try {
        // 처음으로 실행되는 Exception 외에는 실행되지 않는다.
            System.out.println(str.length()); 
            System.out.println(scores[3]);
        } catch(ArithmeticException e){ // 실행 X
            System.out.println("계산이 잘못된 것 같아요.");
        } catch (NullPointerException e) {
            System.out.println("문자열의 길이가 잘못되었습니다.");
        } catch(Exception e){ // 실행 X
            System.out.println("오류가 발생했습니다. ");
        }
    }
}
public class Test {
    public static void main(String[] args) {

        String str = null;
        int[] scores = {10,20,30};
        try {
            System.out.println(str.length()); 
            System.out.println(scores[3]);
        } catch(Exception e){ 
        // 만약 맨처음으로 오는 catch 문에 타입이 Exception인 경우 하위 catch문들은 전부 필요가 없다. 하지만 구체적인 내용을 확인하기는 어렵다 
            System.out.println("계산이 잘못된 것 같아요.");
        } catch (NullPointerException e) { // 실행 X
            System.out.println("문자열의 길이가 잘못되었습니다.");
        } catch(Exception e){ // 실행 X
            System.out.println("오류가 발생했습니다. ");
        }
    }
}

Multi Catch 🚀

하나의 try 블록에서 여러 개의 예외가 발생하는 경우도 있다. 그럴 경우 catch 문을 여러 개 작성해야 한다. 그런 경우에 코드의 중복될 확률도 높아지고 가독성이 떨어지기 때문에 자바 1.7 버전 이후부터 Multi Catch 기능을 제공한다.

try{
 // try 블록에서 여러개의 예외가 발생할 경우가 존재할 수 있다.
 // 각 예외 별로 중복되는 코드가 발생할 가능성이 있다. 그럴 경우 따로 Extract Method 기능을 활용해서 중복을 줄일 순 있지만 결과론 적으로 메소드 호출 코드가 중복 되기 때문에 이조차도 효과를 보긴 어렵다.
}catch(ArrayIndexOutOfBoundsException e1){ 
    ArrayIndexOutOfBoundsException 처리 로직
}catch(NullPointerException e2){
    NullPointerException 처리 로직
}catch(NumberFormatException e3){                                               
    IOException 처리 로직
}
 
try {

} catch(ArrayIndexOutOfBoundsException | NullPointerException | NumberFormatException e) {
  // 하나의 catch 문 안에 or에 해당하는 논리연산 기호를 사용하여 여러개의 예외를 한꺼번에 연결할 수 있고, 가독성도 훨씬 좋아진다.
}

Multi Catch 사용 시 주의할 점 🤔

상황에 따라 여러 가지의 예외를 하나의 로직으로 처리할 수 있는 장점은 있지만, 주의해야 할 점이 있다.

  • 상속관계에 있는 예외는 동시에 사용할 수 없다
try {

} catch (ArrayIndexOutOfBoundsException | RuntimeException e) {
  // 상속관계에 있는 예외는 동시에 사용할 수 없다.
	// ArrayIndexOutOfBoundsException은 RuntimeException 클래스의 자식이기 때문에 부모인 RunTimeException으로 예외처리가 가능하다.
}
try {

} catch (RuntimeException e) {
  // 따라서 RunTimeException 하나만 작성하면 된다.
}
  • Multi Catch 문에 사용되는 예외들은 하나의 참조변수 e로만 처리가 가능하다
try {

} catch (NullPointerException | ArrayIndexOutOfBoundsException | NumberFormatException e) {
// e.printStackTrace(), e.getMessage() 이런 모든 Exception 클래스에 공통으로 들어가는 코드들을 작성할 수 있다.
} 

finally 🚀

finally는 try 구문에서 예외가 발생하는 것과 상관없이 언제나 실행되는 로직이다. 예외가 발생한 경우에는 try -> catch -> finally 순으로 실행되고, 예외가 발생하지 않은 상태에선 try -> finally 순으로 실행된다.

Resource

이미지 파일, 텍스트 파일, 네트워크에 특정 데이터, 데이터베이스 그 밖에 외부에서 가져올 수 있는 데이터들을 Resource라고 이야기 한다.

언제 사용할까?

밥을 먹기 위해선 테이블에 앉아야 한다. 그리고 밥을 다 먹으면 앉아 있었던 테이블에서 일어나야 한다. 자바에서도 Resource를 사용하기 위해선 해당 Resource를 잡고 있어야 하고, 해당 작업이 끝나면 Resource를 놔줘야 한다. 이때 사용하는 메소드가 close() 이다

public class FinallyTest {
    public static void main(String[] args) {
        
        try {
            FileWriter fileWriter = new FileWriter("data.txt");
            fileWriter.write("Hello World"); // 외부 Resource 에 접근하여 데이터를 추가할려고 한다.
            // close 하기 전에 예외가 발생할 수 있기 때문에 close 구문이 실행하지 않을 가능성이 높다.
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

        }
    }
}
public class FinallyTest {
    public static void main(String[] args) {
        
        FileWriter fileWriter = null;

        try {
            fileWriter = new FileWriter("data.txt");
            fileWriter.write("Hello World");
            // close 하기 전에 예외가 발생할 수 있기 때문에 close 구문이 실행하지 않을 가능성이 높다.
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileWriter != null) {
                try {
                    fileWriter.close(); // close 메소드는 throws IOException을 하기 때문에 이를 호출하는 곳에서 예외처리를 해야한다.
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
        }
    }
}

try-with-resources

자바 1.7 버전 이후로 나온 문법이다. 기존에 finally 구문을 이용하여 Resources를 활용한 후 close()를 해야 했다. 하지만 그마저도 한 번 더 예외처리를 해야 하기 때문에 코드가 지저분 한 상태가 되기 때문에 이를 조금이나마 개선하고자 나온 문법이다.

try-with-resource를 사용하기 위해선 해당 클래스가 AutoCloseable 인터페이스를 가지고 있어야 한다. 예제로 사용한 FileWriter 클래스는 AutoCloseable 인터페이스를 가지고 있기 때문에 try-with-resource 구문을 사용할 수 있다.

public class FinallyTest {
    public static void main(String[] args) {
				//() 안에 close 해줘야 하는 코드를 작성하면 된다. 이때 세미콜론은 작성하지 않는다.
        try (FileWriter fileWriter = new FileWriter("data.txt")) {
            fileWriter.write("Hello World");
          	// 자바에서 자동으로 close를 해주기 때문에 close 구문은 작성하지 않는다.
            // 사용한다 한들 컴파일러가 Redundant 'close()' 라고 알려준다. (자동으로 해주기 때문에 중복이 발생한다.)
        } catch(IOException e) {
            e.printStackTrace();
        }
    }
}

예외 발생시키기 🚀

예외를 처리할 수도 있지만 개발자 직접 예외를 발생시킬 수 있는 경우도 있다. 개발자가 예외가 발생하면 안 좋은 거 아닌가? 🤔 근데 왜 자바에선 예외를 발생시킬 수 있는 키워드를 제공할까? 개인적은 생각이지만 그 이유는 사용자로부터 잘못된 값이 들어오는 상황을 막기 위해 예외를 발생시킨다. 아래의 예제는 사람을 나타내는 Person 이라는 클래스에 주민등록 번호를 get 함수로 받아 추후에 DB에 저장한다는 가정하에 코드를 작성하였다.

public class Person { // 주민번호를 사용자로부터 입력받아 저장하는 클래스를 만들었다.

    private String pid = ""; // 사람들의 주민등록번호를 담는 변수

    // 만약 사용자의 실수로 14자리가 아닌 10자리가 들어오게 된 상태로 정보를 DB에 저장한다고 하면
    // 추후에 주민등록번호를 가지고 개발해야 할 기능들에 대해 심각한 오류가 생길 수도 있다.
    public void setPid(String pid) {  
        this.pid = pid; // 이대로 DB에 값이 들어간다면 추후에 심각한 오류가 발생함
    }

    public String getPid() {
        return pid;
    }

    public static void main(String[] args) {
        Person person = new Person();
        person.setPid("970427-1111111"); // 주민등록번호는 '-' 포함 14 자리가 들어와야한다.
    }
}
public class Person {

    private String pid = ""; // 사람들의 주민등록번호를 담는 변수

    // 주민등록번호가 14자리가 아닌경우
    // 강제로 Exception을 발생시켜 사용자에게 주민등록번호를 등록하는 과정에서 문제가 생겼다고 알려줄 수 있다.
    // 이를 통해 사용자로부터 잘못된 값이 들어오는 경우를 막아준다.
    public void setPid(String pid) {
        try {
            if (pid.length() != 14) {
              	// throw 키워드를 이용하여 예외를 발생시켰다.
                Exception exception = new Exception("주민등록번호 입력과정에서 문제가 발생함");
                throw exception;
              
                // throw new Exception("주민등록번호 입력과정에서 문제가 발생함"); 위에 2줄을 한 줄로 바꿀 수 있다.
            }
        } catch (Exception e) {
            System.out.println("주민등록번호는 '-' 포함 14 자리가 들어와야합니다 !!!");
        }
        this.pid = pid;
    }

    public String getPid() {
        return pid;
    }

    public static void main(String[] args) {
        Person throwTest = new Person();
        throwTest.setPid("970427-111111"); // 주민등록번호는 '-' 포함 14 자리가 들어와야한다.

    }
}

예외 던지기 🚀

말 그대로 예외 던지기이다. 흔히 말해 폭탄 돌리기와 동일하다. 현재 메소드에서 예외를 처리하지 않고 호출하는 곳에서 예외를 처리하겠다는 의미이다. 예외가 발생하는 메소드에서 처리하면 되지 굳이 던지기까지 한다고? 🤔 첫 번째 이유로는 throws 문을 통해 해당 메소드가 어떤 Exception을 발생시키는지 예상할 수 있다. 두 번째로는 현재 메소드내에서 예외 처리를 할 필요가 없다고 생각이 드는 경우이다. 세 번째 이유로 협업이다.

import java.io.IOException;

// 이 Person 클래스는 사람의 정보를 저장하는 API라고 가정해보자
// 개발자 A,B 이 들은 공통의 API인 Person 클래스를 이용하여 회원가입, 회원정보 수정을 개발해야 한다.
// 회원가입 실패일 경우 -> 해당 주민등록번호의 형태가 맞지 않습니다.
// 회원정보 수정 실패일 경우 -> 해당 주민등록번호는 DB상에 존재하지 않습니다.
public class Person {

    private String pid = ""; // 사람들의 주민등록번호를 담는 변수

    // 둘 다 동일하게 사용자로부터 주민등록번호를 받아야 하는 부분을 개발해야 하는데 상황에 따라 사용자에게 보여줘야 하는 메세지들이 다르다.
    // 단순히 에외만 던지고, 해당 API를 호출하여 개발하는 개발자에게 구체적인 예외 처리를 넘긴다.
    public void setPid(String pid) throws IOException { // IOException 발생한다는 것을 개발자가 예측할 수 있다.
      // 주민등록번호 패턴에 유/무를 판단하는 기능에만 집중할 수 있다.
        if (pid.length() != 14) {
            throw new IOException("주민등록번호 입력과정에서 문제가 발생함");
        }
        this.pid = pid;
    }

    public String getPid() {
        return pid;
    }


    public static void main(String[] args) {

        DeveloperA A = new DeveloperA();
        A.join();

        DeveloperB B = new DeveloperB();
        B.update();

    }
}

class DeveloperA {
    Person throwTest = new Person();

    public void join() {
        // A라는 개발자가 회원가입에 대한 로직을 처리할 경우
        try {
            throwTest.setPid("970427-11111"); // 주민등록번호는 '-' 포함 14 자리가 들어와야한다.
        } catch (Exception e) {
            System.out.println("해당 주민등록번호의 형태가 맞지 않습니다.");
        }
    }
}

class DeveloperB {
    Person throwTest = new Person();

    public void update() {
        // B라는 개발자가 회원가입에 대한 로직을 처리할 경우
        try {
            throwTest.setPid("970427-111111"); // 회원정보 수정을 위해선 DB에 반드시 회원정보가 저장되어야 한다.
        } catch (Exception e) {
            System.out.println("해당 주민등록번호는 DB상에 존재하지 않습니다.");
        }
    }
}

해당 주민등록번호의 형태가 맞지 않습니다.
해당 주민등록번호는 DB상에 존재하지 않습니다.

Exception Hierarchy 🚀

위에서 언급한 예외(Exception)와 오류(Error)는 Throwable 클래스를 부모 클래스로 삼는다. 모든 예외와 에러들은 Throwable 클래스의 서브 클래스로 존재한다. 그 중 기본이 되는 계층 구조 중에 하나인 예외는 서브 클래스로 여러 종류의 예외 클래스를 담고 있는 그 중 RuntimeException을 제외한 나머지 클래스들을 Checked Exception이라 부르고, RuntimeException을 상속받은 예외 클래스들을 UnChecked Exception이라고 부른다. 에러는 자바 런타임 환경에서 자바 프로그램이 돌면서 jvm에서 발생한 문제들을 에러라고 칭한다. 스택오버플로우 같은 에러가 하나의 예제이다.

Checked / UnChecked Exception 🚀

그림과 같이 자바 예외에는 두 가지 유형이 있다. 하나는 컴파일 시점에서 확인이 가능한 Checked Exception, 런타임 시점에서 확인이 가능한 UnChecked Exception이다.

  • Checked Exception - 컴파일 시 Exception이 발생 여부를 판단해 주고, 만약 발생한다면 try-catch 구문이나, throws를 이용하여 예외를 처리해야 한다.
  • UnChecked Exception - 흔히 말해 런타임 에러라고 부르는 예외인 경우들이다. 즉 RuntimeException을 부모 클래스를 사용하는 Exception 클래스들을 지칭한다.

Checked Exception

public class CheckAndUnCheck {
    public static void main(String[] args) {
      // 파일로 부터 바이트를 입력받아, 바이트 단위로 출력하는 클래스인 FileInputStream 을 사용할려고 한다.
      // 하지만 초기 인자값으로 실제 파일의 이름이 들어가야한다. 우리는 인간이기 때문에 육안으로도 이 파일이 존재 여부를 판단할 수 있지만
      // 컴파일러 입장에선 컴파일시 해당 파일이 있는지 없는지 가늠할 수 없기 때문에 컴파일 에러를 뱉어내고 예외처리 구문을 작성하라고 개발자에게 알려준다.
        FileInputStream fileInputStream = new FileInputStream("file");
    }
}
Unhandled exception: java.io.FileNotFoundException
public class CheckAndUnCheck {
    public static void main(String[] args) {
      // try catch문 혹은 throws 키워드를 작성하여 예외처리 구문을 작성해야 컴파일 에러가 발생하지 않는다.
        try {
            FileInputStream fileInputStream = new FileInputStream("file");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

UnChecked Exception

public class CheckAndUnCheck {
    public static void main(String[] args) {
        int[] arrays = {10, 20, 30};
      // arrays 배열에 최대로 올 수 있는 인덱스 값은 2지만, 만약 실수로 3으로 접근했다고 가정해보자
      // 컴파일 시점에선 아무런 문제가 없다.
        System.out.println(arrays[3]); 
    }
}
// 배열의 인덱스 범위를 벗어났다는 ArrayIndexOutOfBoundsException를 뱉어내고 프로그램은 비정상적으로 종료된다.
// 이렇게 컴파일시 문제는 없지만, 실행 중 비정상적으로 종료되는 경우가 
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 
	at CheckAndUnCheck.main(CheckAndUnCheck.java:9)

커스텀 Exception 생성 🚀

기존의 정의된 예외 클래스 외에 필요에 따라 개발자가 새로운 예외 클래스를 정의하여 사용할 수 있게끔 자바에선 해당 기능을 제공한다. 만드는 방법은 간단한다.

  • Custom Exception 만들기
// CheckedException일 경우 Exception 클래스를 상속받은 후 생성자에서 부모 클래스의 생성자를 사용하면 된다.
// 어떤 Exception인지 알려주기 위해 문자열 변수를 받을 수 있는 생성자를 생성한다.
class MyCheckedException extends Exception{

    public MyException(String message) {
        super(message);
    }
}
//UnCheckedException일 경우 RunTimeException 클래스를 상속받은 후 생성자에서 부모 클래스의 생성자를 사용하면 된다.
// 어떤 Exception인지 알려주기 위해 문자열 변수를 받을 수 있는 생성자를 생성한다.
class MyUnCheckedException extends RuntimeException{

    public MyUnCheckedException(String message) {
        super(message);
    }
}
  • 간단한 예
class MyCheckedException extends Exception{

    public MyException(String message) {
        super(message);
    }
}

public class CheckAndUnCheck {
    public static void main(String[] args) {
        try {
            throw new MyCheckedException("커스텀한 예외입니다.");
        } catch (MyCheckedException e) {
            e.printStackTrace();
        }
    }
}

예외는 처리했는데 그 다음엔 뭘 해야하지? 🤔

곰곰이 생각해 봤는데 지금까지 예외가 발생할 것 같은 경우에 상황에 맞는 해결책을 만들었다. 단순히 로그를 출력하여 개발자가 어떤 예외처리가 발생했는지 육안으로 확인만 할 뿐 그에 따른 별다른 처리를 안한 것 같다는 느낌이 파바박 들었다. 이론상 catch 절 안에 예외가 발생했을 경우 이에 따른 코드를 작성하면 된다. 하지만 지금까지 공부한 이론들을 보아하니 구체적으로 어떻게 작성하는지 감이 오지 않는다. 토비의 스프링을 찾아보게 되었고, 관련된 내용이 너무 많아 간략하게 적어봤다.

토비의 스프링

예외 블랙홀

try {

} catch (Exception e) {
  // 이러한 로그들도 누군가 모니터링 하지 않으면 의미 X
  // 예외 처리시 적절하게 복구기 되던가, 개발자에게 통보해야 한다.
  // 굳이 잡아야 한다면 잡지 말고 예외를 던져라
	e.printStackTrace();
}

예외처리 방법

예외복구
  • 예외 상황을 파악하고 문제를 해결해서 정상 상태로 돌려놓는 것
예외처리 회피
  • 예외처리를 자신이 담당하지 않고 자신을 호출한 쪽으로 던져버리는 것이다. throws 문으로 선언해서 예외가 발생하면 알아서 던져지게 하던가 catch 문으로 일단 예외를 잡은 후 로그를 남기고 다시 예외를 던지는 것
예외 전환
  • 회피와는 달리 발생한 예외를 그대로 넘기는 게 아니라 적절한 예외로 전환해서 던진다는 특징이다. 예를 들어 어떤 정수형 타입의 변수를 0으로 나누면 Arithmeticexception이 발생하는 데 이를 좀 더 구체적으로 DivideByZeroException 혹은 DivideException 식의 적절한 예외로 다시 던진다면 처리하기 훨씬 수월할 것이다.

참고자료 🧾

0개의 댓글