컴퓨터공학 💻 도서관📚
Part2. 6-9 예외 처리하기와 미루기 본문
try-catch 문
- try 블록에는 예외가 발생할 가능성이 있는 코드를 작성하고 try 블록 안에서 예외가 발생하는 경우 catch 블록이 수행됨
(try블록에서 예외가 발생하는 경우 catch블록으로 넘어오는데, 넘어온다고 해서 시스템이 종료가 되는 건 아니다.
catch블록을 쭉 수행을 하고 그 뒤로 수행은 그대로 진행이 된다.)
(예외가 발생하는 경우 예외를 catch 해서 catch블록에서 어떤 일들을 하는데 대부분 catch블록에서 로그를 남긴다.)
(만약에 try-catch문으로 예외처리를 안 하면 그냥 코드가 죽어버린다, 실행이 종료된다. --> 일종의 방탄복?)
- 프로그래머가 예외를 처리해줘야 하는 예 (배열의 오류 처리)
public class ArrayExceptionHandling {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
try{ // try블록 안에 오류 가능성이 있는 코드 작성
for(int i=0; i<=5; i++){
System.out.println(arr[i]);
} // ArrayIndexOutOfBoundsException 라는 Exception이 발생을 하면 e라는 변수에 예외가 넘어온다.
}catch(ArrayIndexOutOfBoundsException e){
System.out.println(e); // e.toString()의 출력과 같다. 최상위 클래스에 정의되어 있는 메서드이기에 당연한 걸지도..?
System.out.println(e.getMessage()); // Exception의 오류 내용을 알려주는 message 를 출력
System.out.println(e.toString()); // Exception의 toString은 (1)exception의 풀네임과 (2)오류 내용을 알려주는 message로 구성 되어 있다.
}
System.out.println("비정상 종료되지 않았습니다."); // 이게 로그
}
}
try-catch-finally 문
- finally 블럭에서 파일를 닫거나 네트웍을 닫는 등의 리소스 해제 구현을 함
(파일이나 네트워크를 쓸 때 시스템 리소스를 오픈을 하는데 오픈을 하고 다 쓰고 나면 close를 해줘야 한다.
그런데 close를 안 해주면 나중에 jvm 같은 얘들이 시스템이 종료되면 close를 해주는데
가령 이 리소스가 계속 구동이 되는 얘면 소켓을 열어놓고 열기만 하고 close를 안 한다.
그런데 시스템에 쓸 수 있는 소켓의 개수가 한정돼 있기 때문에 이런 경우에 오류가 났든 정상 종료가 되었든 간에
이 리소스를 꼭 해제해 줘야 한다.
밑에 코드에서 finally가 하는 일은 오픈된, 사용한 리소스를 해제하는 역할을 한다.) - try{} 블럭이 수행되는 경우, finally{} 블럭은 항상 수행 됨 (return이 있어도 finally는 호출이 된다)
(catch문에서 return; 을 하면 다른 코드는 수행이 안 되는데 finally는 호출이 된다.) - 여러 개의 예외 블럭이 있는 경우 각각에서 리소스를 해제하지 않고 finally 블록에서 해제하도록 구현함
(finally블록에서 모든 리소스를 해제한다 , 안 그러면 여러 개의 try-catch문으로 코드가 난잡해진다.)
// 컴파일러에 의해 예외가 처리 되는 예 (파일 에러 처리)
public class FileExceptionHandling {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("a.txt");
} catch (FileNotFoundException e) {
System.out.println(e);
//return;
}finally{
if(fis != null){
try {
fis.close(); // close() 를 해준다.
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("항상 수행 됩니다.");
}
System.out.println("여기도 수행됩니다.");
}
}
try-with-resources문
- 리소스를 사용하는 경우 close() 하지 않아도 자동으로 해제 되도록 해준다
(위에꺼 까지는 직접 명시적으로 리소스 해제를 위해 close를 호출했는데 이걸 사용하면 자동으로 해제된다.) - 자바 7부터 제공되는 구문
- 자바 9 이전까지는 리소스를 try() 괄호 안에서 선언해야만 한
- close()를 명시적으로 호출하지 않아도 try{}블록에서 열린 리소스는 정상적인 경우나 예외가 발생한 경우 모두 자동으로 해제됨 (finally 가 지저분하게 쓰일 일이 없어진다)
- 해당 리소스 클래스가 AutoCloseable 인터페이스를 구현해야 사용 가능하다
- FileInputStream의 경우에는 AutoCloseable을 구현하고 있음
- 자바 9 부터 리소스는 try() 외부에서 선언하고 변수만을 try(obj) 와 같이 사용할 수 있음
- AutoCloseable인터페이스 구현 실습
public class AutoCloseObj implements AutoCloseable{
@Override
public void close() throws Exception { // AutoCloseable 인터페이스의 close 메서드 구현
System.out.println("리소스가 close() 되었습니다"); // 메서드 안에 로그를 찍는다
}
}
public class AutoCloseTest {
public static void main(String[] args) {
AutoCloseObj obj = new AutoCloseObj(); // AutoCloseable 클래스를 구현한 클래스
try (obj){
throw new Exception(); // Exception을 강제로 발생시키는 코드
}catch(Exception e) {
System.out.println("예외 부분 입니다");
}
}
}
예외 처리 미루기
- 예외 처리는 (1)예외가 발생하는 문장에서 try-catch 블록으로 처리하는 방법과 (2)이를 사용하는 부분에서 처리하는 방법 두 가지가 있음
- throws를 이용하면 예외가 발생할 수 있는 부분을 (2)사용하는 문장에서 예외를 처리하게 할 수 있음
(throws를 쓰면 Exception들이 여기서 발생할 수 있지만 여기서 핸들링을 하지 않고 이 메서드를 쓰는 쪽에서 핸들링을 한다는 말이다)
public class ThrowsException {
// throws 로 예외 미루기
public Class loadClass(String fileName, String className) throws FileNotFoundException, ClassNotFoundException{
FileInputStream fis = new FileInputStream(fileName); //FileNotFoundException 발생
Class c = Class.forName(className); //ClassNotFoundException 발생
return c;
}
public static void main(String[] args) {
ThrowsException test = new ThrowsException();
try {
test.loadClass("a.txt", "java.lang.String");
}catch (FileNotFoundException e) { // 파일이 없을 때
e.printStackTrace();
} catch (ClassNotFoundException e) { // 클래스가 없을 때
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
}
}
하나의 try{}블록에서 예외가 여러개 발생하는 경우
- 여러개의 예외가 발생하는 경우 예외를 묶어서 하나의 방법으로 처리할 수도 있고, (multi-exception , multi-catch)
try {
test.loadClass("a.txt", "java.lang.String");
} catch (FileNotFoundException | ClassNotFoundException e) { // or 연산자 | (왼쪽 조건이 참이어도 오른쪽 조건을 본다.)
e.printStackTrace();
}
- 각각의 예외를 따로 처리할 수도 있음
try {
test.loadClass("a.txt", "java.lang.String");
}catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (Exception e) { // Exception 블록은 맨 마지막에 위치
e.printStackTrace();
}
- Exception 클래스를 활용하여 defualt(기본) 처리를 할 때 Exception 블록은 맨 마지막에 위치해야 함
(최상위 Exception , 남은 예외들은 다 여기로 온다 , 남은 예외들이 자동으로 형변환(업캐스팅) 되서 최상위 Exception 안으로 들어온다.)
'✅🌲강의 복습 노트 > 패캠 JavaSpring 강의,코드 복습' 카테고리의 다른 글
Part2. 6-11 오류의 로그를 남기기 - java.util.logging.Logger 활용 (이해 잘 안 됨...) (3) | 2025.08.15 |
---|---|
Part2. 6-10 사용자 정의 예외 클래스와 그 활용 (1) | 2025.08.15 |
Part2. 6-8 예외 처리는 왜 해야 하나? 자바에서 제공되는 클래스들 (2) | 2025.08.08 |
Part2. 6-7 스트림을 활용하여 패키지 여행 비용 계산하기 (2) | 2025.07.29 |
Part2. 6-6 연산 수행에 대한 구현을 할 수 있는 reduce()연산 (1) | 2025.07.29 |
Comments