컴퓨터공학 💻 도서관📚

Part2. 6-9 예외 처리하기와 미루기 본문

✅🌲강의 복습 노트/패캠 JavaSpring 강의,코드 복습

Part2. 6-9 예외 처리하기와 미루기

들판속초록풀 2025. 8. 14. 09:12

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 안으로 들어온다.)

 

 

Comments