My Profile Photo

DongChanS's blog


수학과 학생의 개발일지


Java (7) - Error, Exceptions

1) Exception

자바에서 오류는 객체이다!

1-1. Exception 클래스

The class Exception and its subclasses are a form of Throwable

that indicates conditions that a reasonable application might want to catch.

The class Exception and any subclasses that are not also subclasses of RuntimeException are checked exceptions. Checked exceptions need to be declared in a method or constructor’s throws clause if they can be thrown by the execution of the method or constructor and propagate outside the method or constructor boundary.

catch가 될 수도 있었던 오류들을 가지고있음.

  • Checked - RuntimeException 을 제외한 모든 Exception

    이 Checked exception들은 method나 constructor 안에 throws clause를 구현함으로써 throw될 수 있음.

    (컴파일러가 체크하여 복구코드를 구현하도록 할 수 있음.)

  • RuntimeException : 코드 작성이 잘못된 오류

    ex)

    • ArithmeticException
    • NullPointerException : 객체를 생성하지 않고 사용했을 때
    • NegativeArraySizeException
    • ArrayIndexOutOfBoundsException
    • SecurityException

1-2. Error 클래스

An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a “normal” condition, is also a subclass of Error because most applications should not try to catch it.

A method is not required to declare in its throws clause any subclasses of Errorthat might be thrown during the execution of the method but not caught, since these errors are abnormal conditions that should never occur. That is, Errorand its subclasses are regarded as unchecked exceptions for the purposes of compile-time checking of exceptions.

catch를 할 수 없는 심각한 문제들임. 그래서 throws 키워드를 쓸 필요가 없음.

  • Unchecked - Error + RuntimeException

    => 얘는 복구가 불가능하기 때문에 컴파일러가 체크하지 않음.

1-3. Error handling

일단 이렇게 에러를 핸들하지 않으면 컴파일조차 되지 않는 경우가 있습니다.

public class TryCatchTest {
    FileInputStream fls;
    public TryCatchTest (String filename) {
        fls = new FileInputStream(filename);
        // java.io.FileNotFoundException 을 핸들하지 않음.
    }

    void readLine() {
        String s;
        BufferedReader buf = new BufferedReader(new InputStreamReader(fls));
        while ( (s = buf.readLine()) != null ){
            // java.io.IOException 을 핸들하지 않음.
            System.out.println(s);
        }
    }
    
    public static void main(String[] args){
        TryCatchTest inputFile = new TryCatchTest("data.txt");
        inputFile.readLine();
        System.out.println("성공적?")
    }
}

  1. try-catch문

    void readLine() {
        String s;
        BufferedReader buf = new BufferedReader(new InputStreamReader(fls));
        try {
            while ( (s = buf.readLine()) != null ){
                // java.io.IOException 을 핸들하지 않음.
                System.out.println(s);
            }
        } catch (IOException e){
            System.out.println(e);
        } finally {
            try {
                if (buf != null) buf.close();
            } catch (IOExeption e){
                e.printStackTrace();
            }
        }
    }
    

    catch문에 에러 서브클래스를 정의함으로써 구현할 수 있다.

    finally문 : 에러 발생 여부와 상관없이 마지막으로 수행해야할 문장

    • Try-with-resources Statement

      종종 try문 뒤에 중괄호가 아니라 그냥 괄호가 포함되는 경우가 있습니다.

      try (BufferedReader br = new BufferedReader(new FileReader(path))) 
      {
          return br.readLine();
      }
      

      이런 경우에는 try문이 끝날 시에(에러가 발생하거나, 정상적으로 끝나거나)는 반드시 위에서 선언된 br객체가 사라지게끔 합니다.

  2. Declare Exception

    예외를 직접 처리하지 않고, 호출된 메서드에게 에러처리를 넘겨버림.

    FileInputStream fls;
    public TryCatchTest (String filename) throws FileNotFoundException {
        fls = new FileInputStream(filename);
        // java.io.FileNotFoundException 을 핸들하지 않음.
    }
    

    throws 에러명 을 통해서 에러를 핸들링할 수 있습니다.

1-4. throw VS catch

다음 코드를 보면서 알아봅시다.

 createFunction(Connection connection) throws SQLException {
      //insert items in the database
 }

 main(){

    try{
     createFunction(connection);
    }
    catch (SQLException e){
      connection.rollback();
    }
 }
  1. throws - the function that throws and exception tells it’s parent function that somenthing it’s wrong. For instance you have a createFunction() throws SQLException where you are trying to insert 100 item in a database but the creation of number 98 fails. The createFunction() is used in your main() who receives this SQLException;

    => createFunction 안에서 에러를 다루지 않고, 에러가 나면 즉시 함수를 중단하고 상위에 있는 main()에게 에러 처리를 넘김.

    => 그래서 반드시 main()이 에러를 처리할 수 있는지 확인해야함.

  2. try/catch - the main() knows that createFunction() is suppose to throw an SQLException if something goes wrong so when it implements it puts it in a try/catch block, this way if an SQLException is actually thrown you can execute a fall-back plan in the catch block such as a database rollback.

    => 그래서 main에 try-catch를 놓음으로써 에러가 발생했을 때에는 connection을 롤백하는 방식으로 구성할 수 있습니다.

그러면 어떤 식으로 이 두가지의 용도를 구분하는게 좋을까요??

참고링크에 잘 설명되어 있습니다.

상품발송() {
    try {
        포장();
        영수증발행();
        발송();
    }catch(예외) {
       모두취소();
    }
}

포장() throws 예외 {
   ...
}

영수증발행() throws 예외 {
   ...
}

발송() throws 예외 {
   ...
}

위와 같이 작성하면 상품발송을 위한 3가지 스텝 중 하나라도 에러가 나면,

상품발송쪽에서 예외처리를 넘겨서 모두 취소하게 만듭니다.

상품발송() {
    포장();
    영수증발행();
    발송();
}

포장(){
    try {
       ...
    }catch(예외) {
       포장취소();
    }
}

영수증발행() {
    try {
       ...
    }catch(예외) {
       영수증발행취소();
    }
}

발송() {
    try {
       ...
    }catch(예외) {
       발송취소();
    }
}

이렇게 작성하면, 영수증 발행은 실패했으나, 발송은 성공할 수도 있기 때문에,

반드시 try-catch가 옳은 선택은 아니라는 것을 알 수 있습니다.

comments powered by Disqus