1. 예외 처리 문법
try {
//일반 예외, 실행 예외 발생 가능 코드
} catch (예외 클래스명 참조 변수명) {
//예외가 발생했을 떄 처리
} finally {
//예외 발생 여부에 상관없이 무조건 실행
}
-try {}
-> 예외가 발생할 수 있는 코드 포함
- catch{}
-> 예외가 발생했을 때 처리할 코드 포함
-> 모든 예외를 처리하는 것은 아니며, 소괄호 안의 예외 타입에 해당하는 예외에 한해서만 처리 가능
-> 예외가 발생했을 때만 동작하며 예외 없이 정상적으로 동작할 때는 실행되지 않음
- finally {}
-> 예외가 발생하든, 발생하지 않든 항상 실행되는 블록
-> 리소스 해제, try{}, catch{} 블록의 공통 기능 코드 포함
-> 생략 가능
try {
System.out.println(3/0);
System.out.println("프로그램 종료");
} catch(ArithmeticException e) {
System.out.println("숫자는 0으로 나눌 수 없습니다.");
System.out.println("프로그램 종료");
}
- try{},catch{} 내의 공통된 코드는 예외 발생 여부와 상관없이 항상 실행되는 코드
-> finally{} 블록을 사용해 작성하면 코드의 중복을 제거 가능
try {
System.out.println(3/0);
} catch (ArithmeticException e) {
System.out.println("숫자는 0으로 나눌 수 없습니다.");
} finally {
System.out.println("프로그램 종료"); //중복된 코드는 finally{} 블록에 입력
}
2. 예외 처리 과정
- ArithmeticException 실행예외가 발생하는 코드
try {
System.out.println(3/0);
}
catch(ArithmeticException e){
System.out.println("숫자는 0으로 나눌 수 없습니다.");
}
finally {
System.out.println("프로그램 종료");
System.exit(0);
}
- 먼저 try{}구문 실행
- 예외가 발생하지 않는다면 catch()블록은 실행안됨
- 예외가 발생하면 자바 가상 머신이 가장 먼저 인지
- 자바 가상 머신은 발생한 예외 타입의 객체를 생성해 catch(){} 블록의 매개변수로 전달
ex) ArithmeticException이 발생하면 JVM은 ArithmeticException 객체를 생성하고,
생성 객체를 catch(){}블록의 매개변수로 전달
- 자바 가상 머신이 생성해 넘겨 준 객체 타입을 catch(){} 블록이 처리할 수 없을때, 예외처리가 되지 않아 프로그램이 강제 종료
3. 다중 예외 처리
- 메서드가 다양한 입력매개변수 타입으로 오버로딩될 수 있는 것 처럼
catch(){}블록도 예외 타입에 따라 여러개 포함 가능
//1) 분모가 0일 때 ArithmeticException을 처리하는 예외 처리 구문
try {
System.out.println(3/0);
}catch (ArithmeticException e) {
System.out.println("숫자는 0으로 나눌 수 없습니다.");
} finally {
System.out.println("프로그램 종료");
}
//2) 숫자가 아닌 문자열을 숫자로 변환하는 과정에서 발생하는 NumberFormatException을 처리하는 예외처리 구문
try {
int a = Integer.parseInt("20A");
}catch(NumberFormatException e) {
System.out.println("숫자로 변환할 수 없습니다.");
}finally {
System.out.println("프로그램 종료");
}
- 각각의 catch(){} 블록을 하나의 예외처리 구문으로 묶어 다음과 같이 표현 가능
try {
System.out.println(3/0);
int a = Integer.parseInt("20A");
}
catch(ArimeticException e) {
System.out.println("숫자는 0으로 나눌 수 없습니다.");
}
catch(NumberFormatException e) {
System.out.println("숫자로 변환할 수 없습니다.");
}
finally {
System.out.println("프로그램을 종료합니다.");
}
- try{}()블록 안에는 예외가 발생할 가능성이 있는 구문이 모두 포함
-> ArithmeticException이 발생하면 첫번째 catch{}()구문이 실행
->NumberFormatException이 발생하면 두번쨰 catch{}()구문이 실행
- 여러개의 catch(){}블록이 있을때 , 실행할 catch(){}블록의 선택과정은 항상 위에서 부터 확인
try {
int a = Integer.parseInt("20A");
System.out.println(3/0);
}
catch(Exception e) {
System.out.println("숫자는 0으로 나눌 수 없습니다."):
}
catch(NumberFormatException e) { // 도달 불가능 코드
System.out.println("숫자로 변환할 수 없습니다.");
}
- 먼저 Exception 타입인지를 확인
- 모든 예외는 Exception 클래스의 하위 클래스 이므로 어떤 예외가 발생하든 첫 번째 catch(){} 블록만 실행
- 두 번째 catch(){} 블록을 절대 도달할 수 없는 코드 (unreachable code)가 되어 오류 발생
- 다중 예외 처리 과정에서 각각의 예외가 발생했을 때 처리하는 내용이 동일할 수 있음
-> 1개의 catch(){}블록이 2개의 예외를 동시에 처리하도록 통합할 수 있다.
-> 각각의 예외 타입은 OR(|) 기호를 사용해 연결
try {
//...
}catch(예외 타입 A | 예외 타입 B 참조 변수명) {
//...
} finally {
//...
}
try {
System.out.println(3/0);
int a = Integer.parseInt("20A");
}
catch(ArithmeticException | NumberFormatException e) {
System.out.println("프로그램을 종료합니다.");
}
4. 리소스 자동 해제 예외 처리
- finally{} 블록의 가장 대표적인 기능은 리소스를 해제
- 리소스 해제 : 더이상 사용하지 않는 자원을 반납하는 것 ex) 자바 입출력 리소스
- try{} 블록에서 리소스를 사용하는 객체를 생성한 후 finally{} 블록에서 리소스를 해제하는 예외 처리 구문
InputStreamReader is = null;
try {
is = new InputStreamReader(System.in);
System.out.println(is.read());
} catch(IOEception e) {
//예외 처리
} finally {
if(is !=null) {
try {
is.close();
} catch(IOException e) {
//예외 처리
}
}
}
- try{} 블록에서는 문자 단위로 입력을 수행하는 InputStreamReader 객체를 생성해 사용
- finally{} 블록에서는 자원을 반납(is.close())
- 리소스 자동 해제 예외 처리
try(리소스 자동 해제가 필요한 객체 생성) {
//예외 발생 가능 코드
}
catch(예외 클래스명 참조 변수명) {
//해당 예외가 발생했을 때 처리하는 블록
}
finally {
//예외 발생 여부에 상관없이 무조건 실행하는 블록
}
- 자동으로 리소스를 반납해야할 객체를 생성하면 예외 처리 구문의 실행이 끝났을 때 리소스가 자동으로 해제
- 예외 처리 구문이 완료되면 try(){} 블록의 소괄호 안에서 생성된 객체 내부의 close() 메서드를 자동으로 호출함으로써
리소스를 자동으로 해제
try(InputStreamReader is = new InputStreamReader(System.in;) {
System.out.println(is.read());
}
catch(IOException e) {
//예외 처리
}
//try with resourse 구문 1
try(InputStreamReader isr1 = new InputStreamReader (System.in);) { //자동 해제
char input = (char) isr1.read();
System.out.println("입력 글자 =" + input);
} catch(IOException e) {
e.printStackTrace();
}
//try with resourse 구문 2
try(InputStreamReader isr2 = new InputStreamReader(System.in);) { //리소스 반납으로 사용불가
char input =(char)isr2.read(); // System.in 리소스가 반납돼 예외 발생
System.out.println("입력 글자=" + input);
} catch (IOException e) {
e.printStackTrace();
}
- try- catch 구문을 끝낼 때 리소스를 해제하기 때문에 이후에는 콘솔 입력을 사용할 수 없게 됨
- System.in : 콘솔 입력을 처리하는 리소스로, 자바 가상 머신이 단 하나의 객체를 생성해 제공하기 때문에 이를 반납하면 더이상 콘솔을 입력할 수 없음
package TryWithResouce;
import java.io.IOException;
import java.io.InputStreamReader;
public class TryWithResouce {
public static void main(String[] args) {
System.out.println("문자를 입력하세요!");
//System.in 리소스를 해제하면 더이상 콘솔 입력 불가
//1.리소스 자동 해제
try(InputStreamReader isr1 = new InputStreamReader(System.in);) {
char input = (char)isr1.read();
System.out.println("입력 글자 ="+ input);
}
catch(IOException e) {
e.printStackTrace();
}
//2.리소스 수동 해제
InputStreamReader isr2 = null;
try {
isr2 = new InputStreamReader(System.in);
char input = (char)isr2.read();
System.out.println("입력 글자 ="+ input);
}
catch(IOException e) {
e.printStackTrace();
}
finally {
//리소스 해제 구문
if(isr2!=null) {
try { //리소스 해제
isr2.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
}
}
- 리소스 자동 해제 예외 처리 구문은 예외의 발생 여부와 관계없이 예외 처리 구문이 완료된 후 리소스 객체의 close() 메서드를 자동으로 호출
- 리소스 객체 내부에 close() 메서드가 있어야 자동해제 할 수 있는 객체가 될 수 있음
- 리소스 자동 해제를 위한 클래스는 반드시 AutoCloseable 인터페이스를 구현해야 함
- AutoCloseable 인터페이스 내부에는 close() 메서드를 포함돼 있음
class A implements AutoCloseable {
String resourse;
A(String resourse) {
this.resourse = resourse;
}
@override
public void close() thros Exception {
resource = null;
System.out.println("리소스 해제");
}
}
- AutoCloseable 인터페이스를 구현한 후 close() 메서드의 내부에서 오버라이딩한 클래스 정의
- 예외처리 구문이 실행된 이후 close() 메서드가 호출 된다는 것을 보이기 위해
내부에서는 필드를 null값으로 초기화 하고 "리소스 해제" 구문만 출력하는 코드 작성
try(A a = new A("특정 파일");) {
}
catch(Exception e) {
} //"리소스 해제"출력
- 명시적으로 close() 메서드의 호출 구문이 없는데도 "리소스 해제"구문이 출력
package TryWithResouce;
class A implements AutoCloseable {
String resource;
A(String resouce){
this.resource = resouce;
}
//@override
public void close() throws Exception {
if(resource!=null) {
resource=null;
System.out.println("리소스가 해제되었습니다.");
}
}
}
public class TryWithResouce {
public static void main(String[] args) {
//1.리소스를 사용하고 finally에서 리소스 수동 해제하기
A a1 = null;
try {
a1 = new A("특정파일");
}catch(Exception e) {
System.out.println("예외 처리");
}finally {
//리소스 수동 해제
if(a1.resource!=null) {
try {
a1.close();
}catch(Exception e) {}
}
}
//2.리소스 자동 해제
try(A a2 = new A("특정 파일");) {
}catch(Exception e) {
System.out.println("예외 처리");
}
}
}
'Java' 카테고리의 다른 글
14 - 4장 사용자 정의 예외 클래스 (0) | 2023.06.13 |
---|---|
14 - 3장 예외 전가 (0) | 2023.06.13 |
14 - 1장 예외 (0) | 2023.06.12 |
13 - 3 장 이너 인터페이스 (0) | 2023.06.05 |
13 - 2 장 익명 이너 클래스 (0) | 2023.06.05 |