티스토리 뷰

728x90
반응형

예외(Exception)란 무엇인가? Exception과 Error의 차이는?


Exception(예외)란?
  • 예외는 갑작스럽게 발생하더라도 해결할 수 있는 프로그램 오류로서 에러보다 비교적 덜 심각한 오류입니다.
  • 프로그래머가 예외를 처리하는 코드를 작성함으로써 방지를 할 수 있습니다.
Error란?
  • 시스템이 종료되어야 할 수준의 상황과 같이 수습할 수 없는 심각한 문제를 의미합니다.
  • 개발자가 미리 예측하여 방지할 수 없습니다.

 

예외 처리 방법


try - catch - finally
  • try 블록에는 예외 발생 가능한 코드가 들어가며 try 블럭 내부에서 예외가 발생하면 즉시 실행을 멈추고 catch 블록으로 이동하여 예외 처리 코드를 실행합니다. 그리고 finally 블록 코드를 실행합니다. finally 블록은 예외 여부와 상관없이 실행이 되며 심지어 try 블럭과 catch 블럭에서 return문을 사용하더라도 실행됩니다.
try { 
    connection = dataSource.getConnection(); 
    ResultSet resultSet = connection.prepareStatement("SELECT * FROM BOARD").executeQuery(); 
} catch (SQLException e){ 
    e.printStackTrace();
} finally {
    ...
}

 

다중 catch
  • catch 블록이 여러개라 할지라도 하나의 catch 블록만 실행이 됩니다. try 블록에서 동시 다발적으로 예외가 발생하지 않고 하나의 예외가 발생하면 즉시 멈추고 해당 catch 블록으로 이동하기 때문입니다.
  • 주의할 점은 상위 예외 클래스가 하위 예외 클래스보다 아래쪽에 위치해야 합니다. 예외를 처리할 catch 블록은 위에서 아래로 차례대로 검색이 되는데 상위 예외 클래스가 위에 위치해 있다면 상위 예외 클래스가 예외를 잡아버리므로 디테일한 처리가 불가능합니다.
try { 
    connection = dataSource.getConnection(); 
    ResultSet resultSet = connection.prepareStatement("SELECT * FROM BOARD").executeQuery(); 
} catch (SQLException e){ 
    e.printStackTrace();
} catch (Exception e){ 
    e.printStackTrace();
}

 

멀티 catch
  • 자바 7부터 하나의 catch 블록에서 여러개의 예외를 처리할 수 있도록 멀티 catch기능이 추가되었습니다.
  • 여러개의 예외를 처리하는 경우 || 로 연결할 수 있습니다.
try { 
    connection = dataSource.getConnection(); 
    ResultSet resultSet = connection.prepareStatement("SELECT * FROM BOARD").executeQuery(); 
} catch (SQLException e || DataAccessException e){ 
    e.printStackTrace();
} catch (Exception e){ 
    e.printStackTrace();
}

 

try-with-resources
  • 아래 코드를 보면 SQL을 사용할 때마다 커넥션을 닫아주어야하는데 JDK 7부터는 AutoCloseable 인터페이스를 구현한 클래스들에 대해 자동적으로 리소스를 회수할 수 있는 문법을 제공하는데 이를 try-with-resources 문법이라고 합니다.
try { 
    connection = dataSource.getConnection(); 
    ResultSet resultSet = connection.prepareStatement("SELECT * FROM BOARD").executeQuery(); 
} catch (SQLException e){ 
    e.printStackTrace();
} finally {
    // 리소스 반납
    try {
        if(ps != null){
            ps.close();
        }
        if(conn != null){
            conn.close();
        }
    } catch(Exception e){
        e.printStackTrace();
    }
}

 

  • 아래 예제는 AutoCloseable을 구현한 간단한 예제입니다.
public class Example implements AutoCloseable{
    Connection connection = null;
    PreparedStatement ps = null;
    ResultSet rs = null;

    public void list() {
        try {
            connection = dataSource.getConnection();
            ResultSet resultSet = connection.prepareStatement("SELECT * FROM BOARD").executeQuery();
        } catch (SQLException e){
            e.printStackTrace();
        }
    }

    @Override
    public void close() throws Exception {
        this.ps.close();
        this.connection.close();
    }
}

 

 

throw
  • 메서드 내에서 사용할 수 있으며 로직을 진행하면서 조건에 따라 명시적으로 예외를 던질 때 사용하는 키워드입니다.
public static void main(String[] args) {
    try {
        if(5 / 0 > 1){
            throw new ArithmeticException();
        }
    } catch (ArithmeticException e) {
        e.printStackTrace();
    }
}

 

throws
  • 메서드 시그니처에 사용 가능하며 해당 메서드를 호출하는 클라이언트에게 예외를 던집니다.
  • 쉼표를 이용하여 여러개의 예외를 던질 수 있습니다.
public static void main(String[] args) throws ArithmeticException, IOException {
    if(5 / 0 > 1){
        ...
    }
}

 

예외 계층 구조


  • Exception과 Error는 Throwable 클래스를 상속받고 있으며 Throwable은 Object를 상속받고 있습니다.

 

Checked Exceptions과 UnChecked Exceptions의 차이


Checked Exceptions
  • 일반 예외 클래스는 Exception을 상속받지만 RuntimeException을 상속받지 않는 클래스들입니다.
  • 컴파일 시점에서 컴파일러에 의해 확인할 수 있는 예외입니다.
  • 프로그램 실행, 구현의 흐름상 예외의 발생 가능성이 있다면 명시적인 예외처리를 작성하게 강제합니다.

 

UnChecked Exceptions
  • 실행 예외는 RuntimeException을 상속 받는 클래스들입니다. RuntimeException 역시 Exception을 상속 받지만 JVM은 RuntimeException을 상속했는지 여부를 보고 실행 예외를 판단하게 됩니다.
  • 런타임 시점에서 발생하는 Exception, Error들을 말합니다.
  • 개발자 부주의로 인한 문제에서 발생하게끔 의도된 것들이나(null 체크, 형변환, 메서드 호출) 시스템에서 발생하는 것들을 말합니다.

 

실행 예외(RuntimeException)
  • 실행 예외는 컴파일러가 체크를 하지 않기 때문에 오직 개발자의 경험에 의해서 예외 처리 코드를 삽입해야 합니다. 만약 개발자가 실행 예외에 대한 예외 처리를 하지 않는다면 프로그램은 종료하게 됩니다.

🧨 NullPointerException

public class NullPointerExceptionExample {
    
    public static void main(String[] args){
        
        String data = null;
        System.out.println(data.toString());   
    }
}

🧨 ArrayIndexOutOfBoundsException

public class Example{

    public static void main(String[] args) {
        System.out.println(args[0]);
    }
}

🧨NumberFormatException

public class Example{

    public static void main(String[] args) {
        String str = "100N";
        int A = Integer.parseInt(str);
    }
}

 

 

커스텀한(사용자 정의) 예외 만드는 방법


  • 사용자 정의 예외 클래스는 컴파일러가 체크하는 일반 예외로 선언하거나, 컴파일러가 체크하지 않는 실행 예외로 선언할 수 있습니다. 일반 예외로 선언하는 경우 Exception을 상속 받고 실행 예외로 선언하는 경우 RuntimeException을 상속 받습니다.
  • 사용자 정의 예외 클래스의 이름은 Exception으로 끝나는것이 좋고 메서드를 포함할 수 있지만 대부분 매개 변수가 없는 생성자 하나와 예외 메세지를 출력할 String 타입의 매개변수를 갖는 생성자를 생성합니다.
public class BalanceInsufficientException extends Exception{

    public BalanceInsufficientException() {}

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

public class Example{

    public static void main(String[] args) throws Exception{
        int balance = 10000;
        int money = 15000;

        withdraw(balance, money);
    }

    public static void withdraw (int balance, int money) throws BalanceInsufficientException {

        if(balance < money){
            throw new BalanceInsufficientException("잔고가 부족합니다.");
        }
    }
}

728x90
반응형

'JAVA > JAVA기본' 카테고리의 다른 글

JAVA - Thread란?  (0) 2022.01.27
JAVA - Thread 클래스와 Runnable 인터페이스  (0) 2022.01.27
JAVA - 인터페이스란?  (0) 2022.01.26
JAVA - Object 클래스란?  (0) 2022.01.16
JAVA - 추상 클래스란?  (2) 2022.01.16