1. 프로그램 오류, 예외 클래스의 계층구조
설명 보기
- 에러 : 프로그램 코드에 의해서 수습될 수 없는 심각한 오류
- 컴파일 에러
- 런타임 에러
- 프로그램 오류
- 예외 : 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류
- 에러는 어쩔 수 없지만, 예외는 처리해야한다.
- 예외가 발생하면 프로그램을 중단하고 오류메시지를 보여준다.
- 예외처리 : 프로그램 실행 시 발생할 수 있는 예외의 발생에 대비한 코드를 작성하는 것
- 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지하는 것
- 예외 클래스의 종류
- 일반 예외 (컴파일러 체크 예외 | Checked Exception) :
- 컴파일하는 과정에서 예외처리코드가 필요한지 검사
- 예외 처리 코드가 없다면 컴파일 오류가 발생
- 실행 예외 (RuntimeException | Unchecked Exception) :
- 컴파일하는 과정에서 예외 처리 코드를 검사하지 않는 예외
- 컴파일 시 예외 처리를 확인하는 차이가 있지만, 둘다 예외 처리가 필요하다.
- 일반 예외 (컴파일러 체크 예외 | Checked Exception) :
- 예외 클래스의 계층 구조
- Object : 최상위 부모 (모든 객체의 최상위 부모)
- Throwable : 최상위 예외
- Error : 메모리 부족이나 심각한 시스템 오류같은 복구 불가능한 예외 | 개발자가 잡을 수 없는 예외
- Exception : 컴파일러가 체크하는 checked exception. 단 RuntimeException은 예외
- 사용자의 실수로 발생하는 예외
- RuntimeException : 컴파일러가 체크하지 않는 unchecked exception, 런타임 예외
- 프로그래머의 실수로 발생하는 예외
일반 예외들
실행 예외들
- 에러 : 프로그램 코드에 의해서 수습될 수 없는 심각한 오류
2. 예외 처리 try-catch
설명 보기
try { <수행할 문장 1>; <수행할 문장 2>; ... } catch(예외1) { <수행할 문장 A>; ... } catch(예외2) { <수행할 문장 a>; ... } ----------------------------------------------------------------------------------- try { <수행할 문장 1>; <수행할 문장 2>; ... } catch (예외1 | 예외2) { // 둘 중 하나가 예외일 경우 A 수행 (멀티 catch) <수행할 문장 A>; ... }
- 수행할 문장 1에서 에러가 발생한다면, 해당 오류에 맞는 catch 로 이동해 실행하고, 끝나면 try를 빠져나간다.
- 만약 상위 exception의 catch문이 하위 exception보다 앞에 위치하면 뒤에있는 하위 exception catch문이 무시된다
- 발생할 수 있는 에러를 다 고려해서 하위 Exception부터 적어야 한다
- 마찬가지로 부모 클래스에서 상위 Exception이 처리되었다면, 자식 클래스에서 그보다 상위의 Exception을 다룰 수 없다. (같거나 하위인 Exception은 사용 가능)
- finally : 어떠한 예외가 발생하든 발생하지 않든 반드시 실행되는 부분
public class DivideExceptionSample { void finalMessage() { System.out.println("그럼 수고하세요."); } public static void main(String[] args) { DivideExceptionSample sample = new DivideExceptionSample(); int result; try { result = 5 / 0; sample.finalMessage(); // 이 코드는 실행되지 않는다. } catch (ArithmeticException e) { result = -1; System.out.println("숫자는 0으로 나눌 수 없습니다."); } finally { sample.finalMessage(); // 이곳에서는 예외와 상관없이 무조건 수행된다. } } }
- try-catch 문 이후에 적는 방법 vs finally : 좀 더 명시적으로 실행하는 부분을 지정할 수 있다.
- file을 open한 상태에서 리소스 반환하는 close를 finally에 넣는다
- try-catch 문 이후에 적는 방법 vs finally : 좀 더 명시적으로 실행하는 부분을 지정할 수 있다.
3. 사용자 정의 예외와 예외발생
설명 보기
- 애플리케이션 서비스와 관련된 예외는 개발자가 직접 정의해서 만들어야한다.
- 따라서 사용자 정의 예외가 필요
- 특정 작업을 강제화 하고싶을 때(Exception을 처리하도록)에도 사용한다.
- 사용자 정의 예외 클래스 선언
public class XXXException extends Exception { public XXXException() { } public XXXException(String message) { super(message); } } or public class XXXException extends RuntimeException { public XXXException() { } public XXXException(String message) { super(message); } } //이런 식으로 디폴트 생성자로 입력인자가 있는 생성자를 호출할 수도 있다. public BalanceInsufficientException() { this("BalanceInsufficientException"); } public BalanceInsufficientException(String message) { super(message); }
- 사용자 정의 예외 블래스는 일반예외 / 실행예외 모두 선언 가능하다.
- 일반 예외 선언 : Exception을 상속
- 실행 예외 선언 : RuntimeException을 상속
- 네이밍은 Exception으로 끝나는 것이 좋다.
- 필드, 생성자, 메소드 선언을 포함할 수 있지만, 보통 생성자 선언만 포함
- Exception을 상속 받으므로 따로 메소드나 필드를 만들어줄 필요가 없다.
- 생성자 2개
- 기본 생성자
public XXXException() { }
- String 타입의 매개 변수를 갖는 생성자
public XXXException(String message) { super(message); }
- 기본 생성자
- 예외 메시지의 용도 : catch 블록의 예외 처리 코드에서 이용하기 위해
- throw : 예외를 최초로 발생시키기
throw new XXXException(); 혹은 throw new XXXException("예외 메시지");
- throws : 자신을 호출한 곳에서 예외를 처리하도록 예외를 떠넘긴다.
public void method() throws XXXException { throw new XXXException("예외 메시지"); }
- throws를 반복해서 사용해 책임을 넘길수는 있지만 좋은 방법이 아니다
- 문제가 발생했을 때 정확한 위치를 찾기 어려워진다.
- 애플리케이션 서비스와 관련된 예외는 개발자가 직접 정의해서 만들어야한다.
4. 예외 트랜잭션 처리 방법
설명 보기
- 트랜잭션 : 작업단위
- 트랜잭션의 하위 프로세스들 중 하나라도 실패하면 모두 취소하고, 트랜잭션 실행 전으로 돌아간다.(롤백)
- 데이터 정합성 : 데이터들의 값이 서로 일관성 있게 일치하는 것
돈_송금() { try { 송금_상태변경(처리중); 송금인_계좌_출금(); 수금인_계좌_입금(); 송금_상태변경(완료); } catch (예외) { 모두취소(); } } 송금_상태변경(status) throws 예외 { ... } 송금인_계좌_출금() throws 예외 { ... } 수금인_계좌_입금() throws 예외 { ... }
package Exception.Account; public class Transfer { public static void main(String[] args) { Account account1 = new Account(); Account account2 = new Account(); long money1 = account1.getBalance(); long money2 = account2.getBalance(); try { account1.withdraw(5000); account2.deposit(5000); } catch (BalanceInsufficientException e) { account1.setBalance(money1); account2.setBalance(money2); } } }
- 트랜잭션 : 작업단위
5. 자동 리소스 닫기(try-with-resource)
설명 보기
- JAVA 7 에서 추가된 try-with-resource 구문
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) { ... } catch (IOException e) { // 예외 처리 }
- 사용 조건 : java.lang.AutoCloseable 인터페이스를 구현하고 있어야 한다.
- AutoCloseable을 구현하는 클래스를 만들어 사용도 가능하다.
public class FileInputStream implements AutoCloseable { private String file; public FileInputStream(String file) { this.file = file; } public void read() { System.out.println(file + " 을 읽습니다"); } @Override public void close() throws Exception { System.out.println(file + "을 닫습니다"); } }
public class TryWithResourceExample { public static void main(String[] args) { try (FileInputStream fileInputStream = new FileInputStream("file.txt")){ fileInputStream.read(); throw new Exception(); // 강제적으로 예외 발생시킴 } catch (Exception e) { System.out.println("예외 처리 코드가 실행되었습니다."); } } }
- AutoCloseable을 구현하는 클래스를 만들어 사용도 가능하다.
6. 기타
- 코딩테스트 준비 열심히 하자
- 어려운 문제보다는 기본개념을 알아간다는 느낌으로
- 자바 로깅 라이브러리 : SLF4J, Logback, Log4J
- e.printStackTrace(); : 오류의 자세한 정보를 출력
7. Daily Quiz
'Dev > ESTsoft 오르미' 카테고리의 다른 글
리스트 (0) | 2024.02.23 |
---|---|
제네릭 (0) | 2024.02.23 |
JVM 조사 : ClassLoader (1) | 2024.02.23 |
인터페이스 (0) | 2024.02.23 |
상속 (0) | 2024.02.23 |