1. 리소스
▷ 데이터를 제공하는 객체
▷ 리소스는 사용하기 위해 열어야(open)하며, 사용이 끝난 다음에는 닫아야(close)합니다.
▷ 리소스를 사용하다가 예외가 발생될 경우에도 안전하게 닫는 것이 중요합니다.
▷ try-with-resources 블록을 사용하면 예외 발생 여부와 상관없이 리소스를 자동으로 닫아줍니다.
1. MyResource 클래스
public class MyResource implements AutoCloseable { private String name; public MyResource(String name) { this.name = name; System.out.println("[MyResource(" + name + ") 열기]"); } public String read1() { System.out.println("[MyResource(" + name + ") 읽기]"); return "100"; } public String read2() { System.out.println("[MyResource(" + name + ") 읽기]"); return "abc"; } @Override public void close() throws Exception { System.out.println("[MyResource(" + name + ") 닫기]"); } }
▷ try-with-resource 블록을 사용하면 예외 발생 여부와 상관없이 리소드를 자동으로 닫아줍니다.
▷ try 괄호에 리소스 여는 코드를 작성하면 try 블록이 정상적으로 실행을 완료했거나 도중 예외가 발생하면 자동으로 리소스의 close() 메소드가 호출됩니다.
▷ 마지막 close 함수의 throws는 close()가 나타나면 Exception으로 넘긴다는 의미입니다.
2. TryWithResourceExample 메인 클래스public class TryWithResourceExample { public static void main(String[] args) { try (MyResource res = new MyResource("A")){ String data = res.read1(); int value = Integer.parseInt(data); } catch(Exception e) { System.out.println("예외 처리 : " + e.getMessage()); } System.out.println(); try (MyResource res = new MyResource("A")){ String data = res.read2(); // NumberFormatException 발생 int value = Integer.parseInt(data); } catch(Exception e) { System.out.println("예외 처리 : " + e.getMessage()); } System.out.println(); // MyResource res1 = new MyResource("A"); // MyResource res2 = new MyResource("B"); // try(res1;res2){ // java 9부터 위의 코드는 실행가능합니다. try( MyResource res1 = new MyResource("A"); MyResource res2 = new MyResource("B"); ){ String data1 = res1.read1(); String data2 = res2.read1(); } catch(Exception e) { System.out.println("예외 처리 : " + e.getMessage()); } } } // 출력 : // [MyResource(A) 열기] // [MyResource(A) 읽기] // [MyResource(A) 닫기] // // [MyResource(A) 열기] // [MyResource(A) 읽기] // [MyResource(A) 닫기] // 예외 처리 : For input string: "abc" // // [MyResource(A) 열기] // [MyResource(B) 열기] // [MyResource(A) 읽기] // [MyResource(B) 읽기] // [MyResource(B) 닫기] // [MyResource(A) 닫기]
▷ 아래의 코드는 두가지 생성자를 동시에 처리할 수 있게 만듭니다.
▷ 값이 정상적으로 입력되면 열고, 읽고 닫는 것까지 원활하게 이어집니다.
▷ 예외가 있더라도 전체적인 동작과 함께 예외가 출력됩니다.
2. 예외 떠넘기기
▷ 메소드 내부에서 예외 발생시 throws 키워드 이용해 메소드를 호출한 곳으로 예외 떠넘기기
▷ throws는 메소드 선언부 끝에 작성합니다. 떠넘길 예외 클래스를 쉼표로 구분해서 나열합니다.
▷ 나열할 예외 클래스가 많으면 throws Exception 또는 throws Throwable 만으로 모든 예외 떠넘기기
◎ 떠넘기기 예제 1
public class ThrowsExample1 { public static void main(String[] args) { try { findClass(); } catch(ClassNotFoundException e) { System.out.println("예외 처리 : " + e.toString()); } System.out.println("프로그램 종료"); } public static void findClass() throws ClassNotFoundException{ Class.forName("java.lang.String2"); } } // 출력 : // 예외 처리 : java.lang.ClassNotFoundException: java.lang.String2 // 프로그램 종료
▷ 메인에서 메소드를 호출하는 것이 아니라 메소드를 찾으러 가는 것입니다.
▷ 메소드에서 throws를 사용하면 forName을 통해 원하는 클래스를 찾고 없으면 예외 처리를 합니다.
◎ 떠넘기기 예제 2
public class ThrowsExample2 { public static void main(String[] args) throws Exception { findClass(); } public static void findClass() throws ClassNotFoundException{ Class.forName("java.lang.String2"); } } // 출력 : // Exception in thread "main" java.lang.ClassNotFoundException: java.lang.String2 // at java.net.URLClassLoader.findClass(URLClassLoader.java:382) // . // . // . // at throws01.ThrowsExample2.findClass(ThrowsExample2.java:10) // at throws01.ThrowsExample2.main(ThrowsExample2.java:6)
▷ main에서 findClass()를 불러오지 않으면 아무리 오류가 발생해도 console 창에 출력이 되지 않습니다.
▷ findClass에서 ClassNotFoundException으로 먼저 예외를 저장하고
main에서 함수를 호출하면 JVM으로 Exception을 보내줍니다.
▶ 따라서 main에서 콘솔 창 호출과 JVM으로 보냈을때 concol 창에 발생하는 오류가 다릅니다.
3. 사용자 정의 예외
▷ 표준 라이브러리에는 없어 직접 정의하는 예외 클래스
▷ 일반 예외는 Exception의 자식 클래스로 선언, 실행 예외는 RuntimeException의 자식 클래스로 선언합니다.
◎ 예외 발생시키기
▷ throw 키워드와 함께 예외 객체를 제공해 사용자 정의 예외를 직접 코드에서 발생시킬 수 있습니다.
▷ 예외의 원인에 해당하는 메세지를 제공하려면 생성자 매개 값으로 전달됩니다.
◎ 사용자 정의 예외 예시 1
1. InsufficientException 클래스
public class InsufficientException extends Exception { public InsufficientException() { } public InsufficientException(String message) { super(message); } }
▷ Exception을 자식 클래스로 선언하고 생성자를 선언합니다.
2. Account 클래스public class Account { private long balance; public Account() {} public long getBalance() { return balance; } public void deposit(int money) { balance += money; } public void withdraw(int money) throws InsufficientException{ if(balance < money) { throw new InsufficientException("잔고 부족 : " + (money-balance) + " 모자람"); } balance -= money; } }
▷ throw new InsufficientException("잔고 부족 : " + (money-balance) + " 모자람");
▶ 다음 문구는 생성자를 예외로 만드는 것입니다.
▶ 생성자 안의 문구는 InsufficientException의 super로 메세지를 출력해줍니다.
3. AccountExample 클래스public class AccountExample { public static void main(String[] args) { Account account = new Account(); // 예금하기 account.deposit(10000); System.out.println("예금액 : " + account.getBalance()); // 출금하기 try { account.withdraw(30000); } catch(InsufficientException e) { String message = e.getMessage(); System.out.println(message); } } } // 출력 : // 예금액 : 10000 // 잔고 부족 : 20000 모자람
★ throw : 고의적으로 예외 발생
★ throws : 예외 던지기 호출한 쪽으로 예외를 넘김
throw를 통해 해당 문장을 고의적으로 예외로 만들어 줄 수 있습니다.
예외가 발생하면 catch를 통해 예외를 출력할 수 있도록 만들어주는 것이 중요하네요!!
다음 장은 문제들을 한 번 볼게요~!
많은 분들의 피드백은 언제나 환영합니다! 많은 댓글 부탁드려요~~
'BackEnd > Java' 카테고리의 다른 글
[java] 이것이 자바다 ch12 java.base 모듈(Object 클래스) (0) | 2023.01.19 |
---|---|
[java] ch11 예외 처리 3 (0) | 2023.01.19 |
[java] ch11 예외 처리 1 (0) | 2023.01.18 |
[java] 이것이 자바다 ch10 라이브러리와 모듈 (0) | 2023.01.17 |
[java] 이것이 자바다 ch09 중첩 선언 2 및 익명 객체 (0) | 2023.01.17 |