본 포스팅은 프로그래머스 자바 입문 강의에 기반하여 작성되었습니다.
자바 강의의 모든 내용이 적힌것이 아닌 복습시 놓쳤던 부분을 하나하나 정리한 내용입니다.
순서 예외 Exception, Throws, Exception 발생시키기, 사용자 정의 Exception
- Exception
프로그램실행중 예기치 못한 사건을 예외라고 한다.
예외 상황을 미리 예측하고 처리할 수 있는데, 이렇게 하는 것을 예외 처리라고 한다.
public class ExceptionExam {
public static void main(String[] args) {
int i = 10;
int j = 5;
int k = i / j;
System.out.println(k);
System.out.println(main 종료!!);
}
}
위 코드에서 j를 0으로 바꾸면 Excption(예외) 발생
j를 0으로 바꾸면 ArithmeticException이 발생하면서 프로그램이 종료된다.
Java는 정수를 정수로 나눌때 0으로 나누면 안된다.
0으로 나누면 오류가 발생하는 것입니다.
- 예외 처리
프로그래머는 j라는 변수에 0이 들어올지도 모르는 예외 상황을 미리 예측하고 처리할 수 있다.
예외처리하는 문법
try-catch-finally
오류가 발생할 예상 부분을 try라는 블록으로 감싼 후, 발생할 오류와 관련된 Exception을 catch라는 블록에서 처리.
오류가 발생했든 안했든 무조건 실행되는 finally라는 블록을 가질 수 있다.
finally블록은 생략가능하다.
try{
예외 발생 가능성이 있는 블록
} catch(예외클래스 변수명) { // 발생할 수 있는 오류와 관련된 Exception 타입
예외 처리 블록
} [ finally {
오류가 생겼든 안생겼든 무조건 실행가능, 생략이 가능함
} ]
예외처리
public class ExceptionExam {
public static void main(String[] args) {
int i = 10;
int j = 0;
try{
int k = i / j;
System.out.println(k);
}catch(ArithmeticException e){
System.out.println("0으로 나눌 수 없습니다. : " + e.toString()); // e.toString예외의 정보를 알려주는 메소드
}finally {
System.out.println("오류가 발생하든 안하든 무조건 실행되는 블록입니다.");
}
}
}
결과값
0으로 나눌 수 없습니다. : java.lang.ArithmeticException: / by zero
오류가 발생하든 안하든 무조건 실행되는 블록입니다.
Exception 처리하지 않았을때는 프로그램이 강제 종료되었는데
catch라는 블록으로 Exception을 처리하니 강제종료되지 않고 잘 실행되는 것을 알 수 있다.
try블록에서 여러종류의 Exception이 발생한다면 catch라는 블록을 여러개 둘 수 있다.
Exception클래스들은 모두 Exception클래스를 상속받으므로,
예외클래스에 Exception을 두게 되면 어떤 오류가 발생하든지 간에 하나의 catch블록에서 모든 오류를 처리할 수 있다.
- throws
throws는 예외가 발생했을때 예외를 호출한 쪽에서 처리하도록 던져준다.
public class ExceptionExam2 {
public static void main(String[] args) {
int i = 10;
int j = 0;
int k = divide(i, j);
System.out.println(k);
}
public static int divide(int i, int j){
int k = i / j;
return k;
}
}
정수를 매개변수로 2개를 받아들인 후 나눗셈을 한 후 그 결과를 반환하는 divide메소드
main메소드에서는 divde메소드를 호출
다음과 같이 divide메소드를 수정
public class ExceptionExam2 {
public static void main(String[] args) {
int i = 10;
int j = 0;
int k = divide(i, j);
System.out.println(k);
}
public static int divide(int i, int j) throws ArithmeticException [,abcException 여러개 가능]{
int k = i / j;
return k;
}
}
메소드 선언 뒤에 throws ArithmeticException 이 적혀있는 것을 알 수 있습니다.
이렇게 적어놓으면 divide메소드는 ArithmeticException이 발생하니 divide메소드를 호출하는 쪽에서 오류를 처리하라는 뜻입니다.
public class ExceptionExam2 {
public static void main(String[] args) {
int i = 10;
int j = 0;
try{
int k = divide(i, j);
System.out.println(k);
} catch(ArithmeticException e){
System.out.println("e.toString");
}
}
public static int divide(int i, int j) throws ArithmeticException{
int k = i / j;
return k;
}
}
강제로 오류를 발생시키는 throw
throw는 오류를 떠넘기는 throws와 보통 같이 사용됩니다.
public class ExceptionExam3 {
public static void main(String[] args) {
int i = 10;
int j = 0;
int k = divide(i, j);
System.out.println(k);
}
public static int divide(int i, int j){
int k = i / j;
return k;
}
}
divide메소드는 2번째 파라미터의 값(int j)이 0일 경우 나누기를 할 때 Exception이 발생한다.
위의 코드를 에러가 발생하지 않게 수정
public class ExceptionExam3 {
public static void main(String[] args) {
int i = 10;
int j = 0;
int k = divide(i, j);
System.out.println(k);
}
public static int divide(int i, int j){
if(j == 0){
System.out.println("2번째 매개변수는 0이면 안됩니다.");
return 0;
}
int k = i / j;
return k;
}
}
결과값
2번째 매개변수는 0이면 안됩니다.
0
j가 0일 경우 안된다는 메시지가 출력되도록 수정하고 0을 리턴.
이렇게 할 경우 main메소드의 k변수는 0값을 가지게 되고 0을 출력하게 된다.
0으로 나눈 결과는 0이 아니다. 0으로 반환하면 더 큰 문제가 발생할수도 있다.
오류를 직접 발생시킨다
에러도 발생하지 않고, 올바르지 않은 결과를 리턴하지 않도록 수정
public class ExceptionExam3 {
public static void main(String[] args) {
int i = 10;
int j = 0;
int k = divide(i, j);
System.out.println(k);
}
public static int divide(int i, int j) throws IllegalArgumentException{
if(j == 0){
throw new IllegalArgumentException("0으로 나눌 수 없어요.");
} //new 라는 연산자를 통해서 IllegalArgumentException 객체를 만든다
int k = i / j;
return k;
}
}
j가 0일 경우에 new연산자를 통하여 IllegalArgumentException 객체가 만들어 진다.
new 앞에 throw 는 해당 라인에서 Exception이 발생한다는 의미이다.
즉 그 줄에서 오류가 발생했다는 것이다. 0으로 나눌수 없습니다. 라는 오류가 발생한것이다.
Exception클래스 이름을 보면 아규먼트가 잘못되었기 때문에 발생한 오류라는 것을 알 수 있다.
divide 메소드를 호출 한 쪽에서의 오류 처리
divide 메소드 뒤에 throws IllegalArgumentException 은 해당 오류는 divide를 호출한 쪽에서 처리를 해야한다는 것을 의미한다.
public class ExceptionExam3 {
public static void main(String[] args) {
int i = 10;
int j = 0;
try{
int k = divide(i, j);
System.out.println(k);
}catch(IllegalArgumentException e){
System.out.println(e.toString());
}
}
public static int divide(int i, int j) throws IllegalArgumentException{
if(j == 0){
throw new IllegalArgumentException("0으로 나눌 수 없어요.");
}
int k = i / j;
return k;
}
}
사용자 정의 Exception
public class 클래스이름 extends Exception {
...
}
Exception이나 Exception의 후손을 상속받아 만들어진 클래스
사용자 정의 예외를 만드는 이유
클래스의 이름만으로 어떤 오류가 발생했는지 알려주어 코드의 직관성을 높인다
Exception 클래스를 상속 받아 정의한 checked Exception
- 반드시 오류를 처리 해야만 하는 Exception
- 예외 처리하지 않으면 컴파일 오류를 발생 시킨다.
RuntimeException 클래스를 상속 받아 정의한 unChecked Exception
- 예외 처리하지 않아도 컴파일 시에는 오류를 발생시키지 않는다.
- 하지만, 모든 예외 상황에 대해서는 적절하게 처리를 하는것이 안정적이다
BizService라는 class가 있다고 가정하자
BizService 클래스에는 업무와 관련된 기능을 가지고있다.
이런 업무와 관련된 메소드를 비지니스 메소드라고 말한다
그렇다면 업무와 관련된 메소드가 실행될 때 오류가 발생하면 어떻게 할까요
해당 메소드는 업무와 관련된 예외가 발생했다고 해당 메소드를 호출한쪽에게 알려야한다
RuntimeException을 상속받은 BizException객체 (unChecked Exception)
public class BizException extends RuntimeException {
public BizException(String msg){
super(msg);
}
public BizException(Exception ex){
super(ex);
}
}
문자열로된 오류메세지와 실제 발생할 Exception을 담는 목적의 생성자 두개를 선언했다
이미 부모클래스가 같은 기능을 가지고 있는 생성자가 있기 때문에 사용자가 정의한 객체에서
따로 할일은 없고 해당 생성자를 부모의 생성자에게 전달만 시켜주면 된다
super메소드에 매개변수로 전달받은 값을 보내주면된다
BizService클래스는 업무를 처리하는 메소드를 가지고 있다고 가정한다.
public class BizService {
public void bizMethod(int i) throws BizException{
System.out.println("비지니스 로직이 시작합니다.");
if(i < 0){
throw new BizException("매개변수 i는 0이상이어야 합니다.");
}
// i가 0보다 작을때 Exception을 발생시킨다
System.out.println("비지니스 로직이 종료됩니다.");
}
}
앞에서 만든 BizService를 이용하는 BizExam클래스
매개변수 값을 -1을 넘길때는 Exception이 발생하기 때문에 try catch블록으로 처리한다.
public class BizExam {
public static void main(String[] args) {
BizService biz = new BizService();
biz.bizMethod(5);
try{
biz.bizMethod(-3);
}catch(Exception ex){
ex.printStackTrace();
}
}
}
실행결과
비지니스 로직이 시작합니다.
비지니스 로직이 종료됩니다.
비지니스 로직이 시작합니다.
javaStudy.BizException: 매개변수 i는 0이상이어야 합니다.
at javaStudy.BizService.bizMethod(BizService.java:5)
at javaStudy.BizExam.main(BizExam.java:6)
'프로그래밍 공부 > JAVA' 카테고리의 다른 글
JAVA 중급 강의정리 java.util 패키지, Generic, 컬렉션 프레임워크 (0) | 2021.08.10 |
---|---|
JAVA 중급 강의정리 Object클래스 ~ java.lang 패키지 (0) | 2021.08.10 |
JAVA 입문 강의정리 인터페이스 (0) | 2021.07.22 |
JAVA 입문 강의정리 상속 (0) | 2021.07.21 |
JAVA 입문 강의정리 (클래스~패키지) (0) | 2021.07.20 |