👨🏻‍💻

[JAVA]예외처리

과목
JAVA
태그
Exception
try-catch
throws
StudyDate
2020/12/28

자바하면서 발생할 수 있는 문제

오류(Error)

시스템 상에서 프로그램에 심각한 문제를 발생하여 실행중인 프로그램이 종료되는 것을 말한다.
개발자가 미리예측이 불가하며 오류에대한 처리는 할 수없다
재부팅이 답!!

예외(Exception)

오류와 마찬가지로 실행중인 프로그램을 비정상적으로 종료시키지만 발생할 수 있는 상황을 미리예측하고 처리할 수 있는 미약한 오류
개발자는 예외처리를 통해 예외상황을 적절히 처리하여 코드의 흐름을 컨트롤 할 수 있음

예외처리 왜 할까?

프로그램 실행시 에러발생 > 프로그램종료 > 이렇게 끝나면안되 > 잡아서 다시복귀시키게 > 원래프로그램흐름 유지

예외처리방법은?

1. throws로 위임
throw는 강제로 예외를 발생시키는 구문이다
throw new 예외클래스명();
흐름은 그림과같다 (1-1 throws흐름)
그림1-1)throws 흐름
throws를 이용하면 프로그램이 예외일때 그 상태에서 바로 종료가 된다.
그래서 마지막 프로그램을 정상적으로 종료합니다라는 문구는 실행이안된다.
ExceptionTest et = new ExceptionTest(); /* 상품 가격 10000원 이고, 가진 돈은 50000원일 때*/ // et.checkEnoughMoney(10000, 50000); // 정상동작 /*상품 가격은 50000원이고, 가진 돈은 10000원일 때*/ -- 예외상황 et.checkEnoughMoney(50000, 10000); System.out.println("프로그램을 정상적으로 종료합니다.");--예외상황일때 실행안됨
Java
복사
package com.greedy.section01.exception; public class ExceptionTest { public void checkEnoughMoney(int price, int money) throws Exception { System.out.println("가지고 계신 돈은 " + money + "원 입니다."); if(money >= price) { System.out.println("상품을 구입하기 위한 금액이 충분합니다."); }else { /* 돈이 충분하지 않은 경우 예외발생 */ throw new Exception(); } System.out.println("즐거운 쇼핑하세요~"); } } -------------------------- ExceptionTest et = new ExceptionTest(); /* 상품 가격 10000원 이고, 가진 돈은 50000원일 때*/ // et.checkEnoughMoney(10000, 50000); // 정상동작 /*상품 가격은 50000원이고, 가진 돈은 10000원일 때*/ et.checkEnoughMoney(50000, 10000); System.out.println("프로그램을 정상적으로 종료합니다.");
Java
복사
2. try-catch로 처리
try -catch문은 오류 발생시 그 오류를 다시 잡아가지고 와서 프로그램이 다시 실행될수 있게 한다.
흐름은 그림(1-2 try-catch)와 같다.
그림1-2) try-catch의 흐름
코드흐름
1.
예외처리를 할 checkEnoughMoney 메서드를 만들고 thorws로 Exception을던진다.
package com.greedy.section01.exception; public class ExceptionTest { public void checkEnoughMoney(int price, int money) throws Exception { System.out.println("가지고 계신 돈은 " + money + "원 입니다."); if(money >= price) { System.out.println("상품을 구입하기 위한 금액이 충분합니다."); }else { /* 돈이 충분하지 않은 경우 예외발생 */ throw new Exception(); } System.out.println("즐거운 쇼핑하세요~"); } }
Java
복사
2. throw Exception을 던지면 메서드를 호출하는 쪽에서 책임을져야한다는의미이다
메소드를 호출하면서 try-catch구문을 쓴다.
정상적으로 작동할 때는 try구문이 작성되며
그렇지 않을때 catch가 오류를 잡아서 다시끌고와서 프로그램을 작동시키게한다.
예외발생일때 상품구입불가라는 콘솔창에 출력문이 뜨게되고
마지막에 프로그램종료합니다 라는 출력문도 뜨게된다.
package com.greedy.section01.exception; public class Application2 { public static void main(String[] args) { /* try-catch 이용하는 방법*/ ExceptionTest et = new ExceptionTest(); try { et.checkEnoughMoney(50000, 10000); System.out.println("============= 상품 구입 가능 ============="); } catch (Exception e) { // e.printStackTrace(); System.out.println("============= 상품 구입 불가 ============="); } System.out.println("프로그램을 종료합니다 "); } }
Java
복사

예외처리시 개발자가 예외문구를 만들수 있다?없다?

정답은 YES!!

사전에 정의된 예외 클래스외에 개발자가 원하는 명칭의 예외클래스를 작성하는 것이 가능하다. extends Exception으로 예외처리 클래스를 상속받아 더 구체적인 예외 이름을 정의하는 것이다.

어떻게 만들까...?

1.
Exception 상속을 받아 클래스를 작성한다
2.
자손클래스에서 부모클래스에 초기화한 생성자를 super()를 사용해 불러온다.
예 ) NotEnoghMoneyExcetion 클래스를 만들어 Exception을 상속받는다
기본생성자 및 초기화하는 생성자를 만듬
package com.greedy.section02.userexception.exception; public class NotEnoughMoneyException extends Exception { /*사용자 정의의 예외 클래스를 만들기 위해서는 Exception 클래스를 상복받으면된다.*/ /*Exception 클래스는 Throwable 클래스를 상속받아서 구현되어있다. * Throwable은 Error 와 Exception 두 가지를 추상화해서 만들었다. * 예외는 Exception의 가장 최상위 클래스이다. * 따라서 오류 상황을 만들 것은 아니기 때문에 Exception클래스를 상속 받는다. * */ /*기본 생성자*/ public NotEnoughMoneyException() { } /*문자열을 부모생성자 쪾으로 전달하며 초기화하는 생성자*/ public NotEnoughMoneyException(String message) { super(message); } }
Java
복사
2.클래스를하나만들어 throws를 이용해 NotEnoughMoneyException을 던져준다
그리고 throw new NotEnoughMoneyException("가진 돈 보다 상품 가격이 더 비쌉니다");라는
사용자 정의문구를 만들어준다
package com.greedy.section02.userexception; import com.greedy.section02.userexception.exception.NotEnoughMoneyException; public class ExceptionTest { public void checkEnoughMoney(int price , int money) throws NotEnoughMoneyException { /*아까 만들었던 Exception을 발생시킨 메소드는 그냥 예외라는 것을 발생시킨 것이다. * 예외 클래스의 이름만으로도 어떠한 예외가 발생했는지를 알 수 있도록 * 사용자 정의의 예외클래스를 추가하여 명명할 것이다. * * */ /*위의 두 값이 정상 입력 되더라도 상품 가격이 가진 돈보다 큰 경우 예외 발생*/ if(money < price) { throw new NotEnoughMoneyException("가진 돈 보다 상품 가격이 더 비쌉니다"); } /*모든 조건이 만족하는 경우 정상적으로 물건 구입가능*/ System.out.println("가진 돈이 충분합니다. 즐거운 쇼핑하세요~"); } }
Java
복사
3. 실행클래스에서 try- catch로 잡는다
package com.greedy.section02.userexception; public class Application1 { public static void main(String[] args) { /* 사전에 정의되어 있는 Exception의 종류는 굉장히 많이 있다. * 하지만 RuntimeException의 후손 대부분은 예외처리를 강제화 하지 않는다. * 이 부분은 뒤에서 다시 다룬다. * */ /*사전에 정의된 예외 클래스외에 개발자가 원하는 명칭의 예외클래스를 작성하는 것이 가능하다. * extends Exception으로 예외처리 클래스를 상속받아 더 구체적인 예외 이름을 정의하는 것이다. * 여기서는 사용자 정의의 예외로 아까 만들었던 프로그램을 조금 더 업그레이드 시켜보자. * */ ExceptionTest et = new ExceptionTest(); try { /*돈이 부족한 경우*/ et.checkEnoughMoney(70000, 50000); } catch(Exception e) { e.printStackTrace(); }
Java
복사
4. 출력화면

예외구문에서 e.getmessage()이용 및 finally 블럭

e.getmassage를 통해 출력문구를 불러올수 있으며 finally는 try-catch문에 상관없이 무조건 동작한다.
그리고 예외구문만들 때 상위타입은 반드시 아래에 작성해야한다.
작성순서는 하위타입>>>> 상위타입 순(위 >>> 아래) 순으로
package com.greedy.section02.userexception; import com.greedy.section02.userexception.exception.MoneyNegativeException; import com.greedy.section02.userexception.exception.NegativeException; import com.greedy.section02.userexception.exception.NotEnoughMoneyException; import com.greedy.section02.userexception.exception.PriceNegativeException; public class Application2 { public static void main(String[] args) { ExceptionTest et = new ExceptionTest(); try { et.checkEnoughMoney(40000, 30000); /*디테일한 예외 상황별로 처리 로직을 다르게 할 수있다. * 이 떄 주의할 정믄 catch 블럭은 위에서 아래로 자신의 탑이과 맞는 경우 동작하기 때문에 * 상위 탑이 위쪽에 오게되는 경우에는 하단에 작성한 코드는 절대 도달할 수 없는 코드가 되므로 * 컴파일 에러가 난다. * 그래서 적용할 때 어떤게 상위타입인지 하위타입인지 잘 확인하고 써야한다.*/ } catch (PriceNegativeException e) { System.out.println("PriceNegativeException 발생!"); System.out.println(e.getMessage()); } catch (MoneyNegativeException e) { System.out.println("MonetNegativeException 발생!"); System.out.println(e.getMessage()); } catch (NegativeException e) { System.out.println("NegativeException"); System.out.println(e.getMessage()); } catch (NotEnoughMoneyException e) { System.out.println("NotEnoughMoneyExceptuin 발생!"); System.out.println(e.getMessage()); } finally { /* 예외 발생여부와 상관 없이 실행할 내용 */ System.out.println("finally 블럭 내용 동작함..."); } System.out.println("프로그램을 종료합니다."); } }
Java
복사

JAVA1.7부터 나온 Multi-Catch를 알아보자!

Multi-Catch란??

JAVA1.7버전부터 추가 된 구문으로 동일한 레벨의 다른타입의 예외를
하나의 catch블럭으로 다룰 수 있다.
package com.greedy.section02.userexception; import com.greedy.section02.userexception.exception.MoneyNegativeException; import com.greedy.section02.userexception.exception.NotEnoughMoneyException; import com.greedy.section02.userexception.exception.PriceNegativeException; public class Application3 { public static void main(String[] args) { /*multi-catch * JDK 1.7에서 추가된 구문으로 * 동일한 레벨의 다른 타입의 예외를 하나의 catch블럭으로 다룰 수 있다. * */ ExceptionTest et = new ExceptionTest(); try { et.checkEnoughMoney(20000, 10000); } catch (PriceNegativeException | MoneyNegativeException e) { /*e.getMessage()로 발생한 예외 클래스의 정보를 알 수 있다.*/ System.out.println(e.getClass() + "발생!"); /*e.getMessage()로 예외 발생시 전달한 메세지를 문자열로 반환받을 수 있다.*/ System.out.println(e.getClass()); } catch (NotEnoughMoneyException e) { /*예외 클래스명, 예외 발생위치, 예외 메세지등을 stack 호출의 역순으로 * 빨간색 글씨를 이용하여 로그형태로 출력해주는 기능을 제공한다. * */ e.printStackTrace(); } finally { /*예외 발생여부와 상관없이 실행할 내용*/ System.out.println("fnally블럭의 내용이 동작함"); } System.out.println("프로글매을 종료합니다."); } }
Java
복사

Runtime Exception 후손클래스

NullPointerException을 안나게 방지하는법

IOException보다 EOFException이 더 구체적이다

예외클래스가 가장많이쓰이는곳 IO(Input/Output)패키지!!

package com.greedy.section3.uses; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class Application1 { public static void main(String[] args) { /*예외 처리를 많이 사용하는 패키지는 io(input/output) 패키지이다. */ BufferedReader in = null; try { /*FileReader라는 클래스의 새엇ㅇ자에 예외를 throws 해 놓았다 * 사용하는 쪽에서 반드시 에외처리를 해야하기 때문에 try-catch 블럭 안에서 생성자를 호출해야한다. * */ in = new BufferedReader(new FileReader("test.dat")); String s; while((s = in.readLine()) != null ) { System.out.println(s); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { /* 예외 발생여부와 상관없이 반드시 처리할 로직 작성 * 주로 자원을 반납할 목적으로 사용한다.*/ try { /*NullPointerException이 발생 * 파일을 찾지못해 객체를 생성하지 못하고 래퍼런스 변수는 null값을 가진 상태이기 때문에 * null 을 참조하는 상태에서 참조연산자를 사용하면 발생하는 예외이다. * NullPointerException은 unchecked Exception으로 try-catch로 처리하기보다는 * 보통 if-else 구문으로 해결 가능하다. * */ if(in != null) { /* 입출력에서 사용한 스트림을 닫아주는 메소드이다. * IOException을 위임한 메소드 이기 떄문에 * finally 블럭 안이라도 예외처리를 중첩으로 해주어야한다. * try블럭과 finally 블럭은 별개이다. * */ in.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
Java
복사