프로그램을 만들다보면 다양한 오류가 발생한다.
이를 대처하기 위한 자바의 예외처리(try...cathc, throws) 방법을 알아보도록 하자
존재하지 않는 파일 열기 - FileNotFoundException
예외 발생
BufferedReader br = new BufferedReader(new FileReader("없는파일"));
br.readline();
br.close();
(오류구문)
Exception in thread "main" java.io.FileNotFoundException: test.txt (No such file or directory)
at java.base/java.io.FileInputStream.open0(Native Method)
at java.base/java.io.FileInputStream.open(FileInputStream.java:219)
...
숫자/0 - ArithmeticException
예외 발생
int c = 4/0;
(오류구문)
Exception in thread "main" java.lang.ArithmeticException: / by zero
at test.main(test.java:37)
배열 범위 오류 - ArrayIndexOutOfBoundsException
오류
int [] a = {1,2,3};
System.out.println(a[3]);
(오류구문)
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
at test.main(test.java:39)
try{
...
} catch(예외1){
...
} catch(예외2){
...
...
}
try
문내 수행할 문장들에 예외가 발생하지 않는다면 catch
문 미수행try
문내 문장 수행 중 예외 발생 시 catch
문 수행 * 숫자를 0으로 나눴을때 발생하는 예외처리
int c;
try{
c=4/0;
} catch(AritmeticException e){ // e는 Ari~의 객체(오류객체)
c = -1; // 예외가 발생되어 문장 수행
}
catch문
으로 미실행public class Sample{
public void shouldBeRun(){
System.out.println("ok thanks.");
}
public static void main(String[] args){
Sample = sample = new Sample();
int c;
try{
c = 4/0;
sample.shouldBeRun(); 해당 코드 실행되지 않음
}catch (ArithmeticException e){
c=-1;
}
}
}
public class Sample{
public void shouldBeRun(){
System.out.println("ok bye~");
}
public static void main(String[] args){
Sample sample = new Sample();
int c;
try{
c=4/0;
} catch (ArithmeticException e){
c=-1;
} finally {
sample.shouldBeRun(); // 예외 상관없이 무조건 수행
}
}
}
이번에는 예외를 발생시켜보도록 한다.
class FoolException extends RuntimeException{
}
public class Sample{
public void sayNick(String nick){
if("fool'.equals(nick)){
throw new FoolException(); // 에러 발생
}
public static void main(String[] args){
Sample sample = new Sample();
sample.sayNick("fool");
sample.sayNick("gorgeous");
}
}
(오류구문)
Exception in thread "main" FoolException
at Sample.sayNick(sample.java:7)
at Sample.main(Sample.java:14)
FoolException이 상속받은 클래스는 RuntimeException이다. Exception은 크게 두가지로 구분된다.
1) RuntimeException (Unchecked Exception)
2) Exception (Checked Exception)
class FoolException extends Exception{
}
public class Sample{
public void sayNick(String nick){
try{
if("fool".equals(nick)){
throw new FoolException();
}
System.out.println("입력된 값은 "+nick+"입니다.");
}catch(FoolException e){
System.out.println("FoolException이 발생했다.");
}
}
public static void main(String[] args){
Sample sample = new Sample();
sample.sayNick("fool");
sample.sayNick("gorgeous");
}
}
sayNick 메소드에서 try...catch
문으로 FoolException을 처리했다.
위 예제는 sayNick 메서드에서 FoolException을 발생과 예외 처리를 했으나, 이렇게 하지 않고 sayNick을 호출한 곳에서 FoolException을 처리하도록 예외를 위로 던질 수 있는 방법에 대해 알아보겠다.
예 - 예외를 위로 던지기
public class Sample{
public void SayNick(String nick) throws FoolException{
if("fool".equals(nick)){
throws new FoolException();
}
System.out.println("입력된 값은 "+nick+"입니다.");
}
public static void main(String[] args){
Sample sample = new Sample();
sample.sayNick("fool");
sample.sayNick("gorgeous");
}
}
sayNick 메소드 뒷부분에 throws 구문을 사용해 FoolException을 위로 보낼 수 있다.(예외 뒤로 미루기)
FoolException 구문은 기존 sayNick 메소드에서 main메소드에서 처리
위의 컴파일 오류 처리(main 메소드 변경)
class FoolException extends Exception{
}
public class Sample{
public void sayNick(String nick) throws FoolException{
if("fool".equals(nick)){
throw new FoolExcetpion();
}
System.out.println("입력된 값은 "+nick+"입니다.");
}
public static void main(String[] args){
Sample sample = new Sample();
try{ // 추가
sample.sayNick("fool");
sample.sayNick("gorgeous");
}catch (FoolException e){
System.out.println("FoolException 발생");
}
}
}
위 예제를 통해 두 가지 메소드에서 예외처리를 해봤다. FoolException은 sayNick메소드에서 처리하는 것이 좋을까 main 메소드에서 처리하는 것이 좋을까? 이 두가지는 큰 차이가 있다.
sample.sayNick("fool"); // FoolException 출력
sample.sayNick("gorgeous"); // gorgeous 출력(수행 O)
sample.sayNick("gorgeouse")
수행 된다.try{
sample.sayNick("fool");
sample.sayNick("gorgeous"); // 이 문장은 수행되지 않는다.
}catch(FoolException e){
System.err.println("FoolException 발생);
}
sample.sayNick("gorgeous")
는 수행되지 않음
이미 첫 문장에서 예외가 발생해catch
문으로 빠지기 때문
try
) / 작업을 취소한다.(catch
) / 예외 처리(throws
) 와 같이 사용.쇼핑몰의 "상품 발송" 트랜잭션을 가정해보자.
트랜잭션에는 다음과 같은 작업들이 있으며, 이 3가지 일들 중 하나라도 실패시 모두 취소하고 "상품발송" 전 상태로 돌린다.
아래와 같이 포장, 영수증 발행, 발송 메서드에서는 예외를 throw
하고 상품발송 메서드에서 throw
된 예외를 처리해 모두 취소하기
* pseudocode *
상품발송(){
try{
포장();
영수증발행();
발송();
}catch(예외){
모두취소(); // 하나라도 실패하면 모두 취소.
}
}
포장() throws 예외{
...
}
영수증발행() throws 예외{
...
}
발송() throws 예외{
...
}