Skip to the content.

- 학습 목표 달성 확인 목록

- [] 예외의 종류에 무엇이 있는지 아는가?

- [] 시스템 예외를 다루는 클래스와 애플리케이션 예외를 다루는 클래스를 아는가?

예외는 두가지로 나눠지는데

Error는 시스템 예외로 적절히 안내메시지를 띄우거나 log파일에 남기고 현재 작업 중인 데이터를 파일로 백업한 후.

애플리케이션을 종료한다.

애플리케이션 예외는 오류에 대한 적절한 조치를 취한 후 애플리케이션을 계속 실행한다.

- [] 시스템 예외 클래스와 애플리케이션 예외 클래스의 계층도를 그릴 수 있는가?

상위 참조

- [] 예외를 처리하는 try ~ catch ~ 문법을 사용할 수 있는가?

public class Exam0110 {
    static void m() {
        //예외를 호출자에게 알려주는 문법
        //throw [Throwable 객체];
        //throw new String("예외가 발생했습니다");컴파일 오류
        throw new RuntimeException("예외가 발생했습니다");//예외발생시 main메서드에게 떠넘긴다
    }

    public static void main(String[] args) {
        try {//예외를 받았을 때 처리하는 문법
            m();
        } catch (RuntimeException e) {
            /*
            예외가 발생하면 catch블록이 실행된다
            코드에서 던진 예외 객체는 catch의 파라미터가 받는다
            catch 블록에는 예외에 대한 적절한 조치를 수행하는 코드를 둔다
            예)다음과 같이 예외가 발생된 이유를 간단히 출력할 수 있다
             */
            System.out.println(e.getMessage());
        }
        System.out.println("시스템을 종료합니다");
    }
}

- [] 여러 개의 catch 블록을 다룰 수 있는가?

먼저 발생하는 예외를 모두 나열 했을때

public class Exam0310 {

    //메서드에서 발생되는 예외는 메서드 선언부에 모두 나열해야 한다
    static void m(int i) throws Exception,RuntimeException, SQLException, IOException {
        if (i == 0) {
            throw new Exception();
        } else if (i == 1) {
            throw new RuntimeException();
        } else if (i == 2) {
            throw new SQLException();
        } else {
            throw new IOException();
        }
    }

    public static void main(String[] args) {

    }
}

나열된 모든 예외를 공통분모를 사용하여 퉁치는 방법

public class Exam0320 {
    //공통 분모를 사용하려 퉁치는 방법
    //메서드에서 발생하는 예외의 공통 수퍼 클래스를 지정하여
    //여러 개를 나열하지 않을 수 있다
    //그러나 호출자에게 어떤 오류가 발생하는지 정확하게 알려주는 것이
    //유지보수에 도움이 된다
    //따라서 가능한 그 메서드에서 발생하는 예외는 모두 나열하라
    static void m(int i)throws Exception {
        if (i == 0) {
            throw new IOException();
        } else if (i == 1) {
            throw new RuntimeException();
        } else if (i == 2) {
            throw new SQLException();
        } else {
            throw new Exception();
        }
    }

    public static void main(String[] args) {

    }
}

- [] 수퍼 클래스 파라미터로 여러 개의 catch 블록을 한 개의 catch 블록으로 통합하는 방법을 아는가?

public class Exam0410 {

    static void m(int i) throws Exception, RuntimeException, SQLException, IOException {
        if (i == 0) {
            throw new Exception("Exception");
        } else if (i == 1) {
            throw new RuntimeException("RuntimeException");
        } else if (i == 2) {
            throw new SQLException("SQLException");
        } else {
            throw new IOException("IOException");
        }
    }

    public static void main(String[] args) throws Exception {
        m(1);//해당 메서드를 호출하려면 throws Exception를 main메서드에 선언해야 한다

        try {//위와 같이 선언을 안하려면 try-catch문을 사용하여 메서드에서 던진 예외를 catch가 잡아와서
             //에러메시지를 개발자에게 알려준다.
            m(1);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }
}
**- [] 연산자를 사용하여 여러 개의 예외를 한 개의 catch 블록에서 받을 수 있는가?**
public class Exam0460 {

    static void m(int i) throws Exception,RuntimeException, SQLException, IOException {
        if (i == 0) {
            throw new Exception("0");
        } else if (i == 1) {
            throw new RuntimeException("1");
        } else if (i == 2) {
            throw new SQLException("2");
        } else {
            throw new IOException("...");
        }
    }

    public static void main(String[] args) throws Exception {

        try {
            m(1);
        } catch (RuntimeException | SQLException | IOException exception) {
            //or연산자로 여러 개의 예외를 묶어서 받을 수 있다
            System.out.println(exception.getMessage());
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

- [] throw 키워드를 사용하여 예외를 던질 수 있는가?

public class test {
    static void m(int i) throws Exception {//해당 메서드에서 예외가 발생하면 그 예외를 던진다
        if (i == 1) {
            throw new Exception("e");
        } else if (i == 2) {
            throw new IOException("i");
        } else if (i == 3) {
            throw new RuntimeException("r");
        } else {
            throw new SQLException("s");
        }
    }

    public static void main(String[] args) {
        try {//해당 메서드가 예외를 발생시키면 try-catch로 예외를 잡아와야한다
             //안그러면 예외를 그대로 보여주면서 애플리케이션을 멈추게한다
            m(2);
        } catch (Exception e) {
            System.out.println(e.getMessage());//해당 예외의 메시지 출력
            e.printStackTrace();
        }
    }
}

- [] 메서드 선언부에 throws 키워드를 언제 사용해야 하는지 아는가?

위의 방식과 같이 try-catch문을 사용하지 않고 또 다른 메서드에게 그 예외를 잡는 것을 넘길때 사용한다

하지만 main메서드에서도 throws 키워드를 사용하여 다른 메서드에게 책임을 양도하면 예외 발생시 애플리케이션은 멈추게 된다

그러므로 main메서드는 최후의 보루로 생각하고 다른 메서드에서 예외 처리를 하던가 main메서드에서 try-catch문을 사용하여 

애플리케이션을 멈추지 않게 만든다.

public class test {
    static void m(int i) throws Exception {//해당 메서드에서 예외가 발생하면 그 예외를 던진다
        if (i == 1) {
            throw new Exception("e");
        } else if (i == 2) {
            throw new IOException("i");
        } else if (i == 3) {
            throw new RuntimeException("r");
        } else {
            throw new SQLException("s");
        }
    }

    public static void main(String[] args) throws Exception {
        m(2);
    }
}

- [] 언제 메서드 선언부에 throws 키워드를 생략하는지 아는가?

public class test {
    static void m(int i) throws Exception {//해당 메서드에서 예외가 발생하면 그 예외를 던진다
        if (i == 1) {
            throw new Exception("e");
        } else if (i == 2) {
            throw new IOException("i");
        } else if (i == 3) {
            throw new RuntimeException("r");
        } else {
            throw new SQLException("s");
        }
    }

    public static void main(String[] args) /*throws Exception 생략됨*/{
        try {//try과 catch문을 사용하면 throws Exception을 생략할 수 있다
            m(2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

- [] Exception과 RuntimeException 예외의 차이를 아는가?

Exception:사용자의 실수와 같은 외적인 요인에 의해 발생하는 예외이다

반드시 try-catch문으로 잡아야되며 안하면 컴파일 에러가 뜬다

RuntimeException:try-catch문으로 잡지 않아도 컴파일은 가능하다

실행할때 에러가 발생하며 프로그래머의 실수로 발생하는 예외이다.

여기서 대표적인 에러인 NullPointerException은 절차적으로 해당 코드의 오류를 발생하면 에러메시지가 뜨면서 

애플리케이션이 멈춘다.

*참고로 필자는 NPE가 제일 싫은 에러…

- [] finally 블록의 사용법을 아는가?

정상적으로 실행하든 아니면 예외가 발생하여 catch 블록을 실행하든

finally문은 무조건 실행한다

즉 try catch 블록을 나가기 전에 반드시 실행한다

그래서 이 블록에는 try에서 사용한 자원을 해제시키는 코드를 주로 둔다

->자원 해제 코드를 둔다

->자원?파일, DB 커넥션, 소켓 커넥션, 대량의 메모리 등

try{
...
}catch(...){
...
}finally{
...
}

- [] try-with-resources 문법을 사용할 수 있는가?

Scanner 메서드와 같이 자원을 쓰고 꼭 해제를 시켜야되는 코드를 넣어야하는데

그 코드를 매번 finally 블록을 만들어 작성하기는 귀찮다

그래서 try with resources 라는 문법을 사용하면 굳이 finally블록에서 close() 를 직접 호출할 필요가 없다

자동으로 처리하기 때문이다

단 java.lang.AutoCloseable 구현제에 대해서만 가능하다

public class Exam0630 {
    static void m()throws Exception {
        try (Scanner scan = new Scanner(System.in);
             // FileReader 클래스도 java.lang.AutoCloseable 구현체이다.
             FileReader in = new FileReader("Hello,java")
        ) {
            System.out.println("입력>");
            int value = scan.nextInt();
            System.out.println(value * value);
        }
    }

    public static void main(String[] args) {
        try {
            m();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

- [] 예외 클래스를 상속 받아 사용자 정의 예외 클래스를 만들 수 있는가?

%[https://gist.github.com/osk2090/ee196608c5c5bf967ae58ea9d1fda773]

- [] 사용자 예외 클래스를 만드는 목적을 아는가?

실무에서 개발자에게 예외의 의미를 직관적으로 알 수 있도록 RuntimeException 같은

평범한 의미가 모호한 이름의 클래스를 사용하지 않고

대신에 기존 예외를 상속받아 의미있는 이름으로 서브 클래스를 정의하기 위해서이다.