티스토리 뷰

Goal 

 - 오류와 예외 클래스에 대해 알아본다

 - 예외 처리의 다양한 방식에 대해 알아본다

 

1. 오류란 무엇인가?

 - 컴파일 오류 : 프로그램 코드 작성 중 발생하는 문법적 오류 

 - 실행 오류 : 실행 중인 프로그램이 의도 하지 않은 동작을 하거나(bug) 프로그램이 중지 되는 오류 (runtime error)

 - 자바는 예외 처리를 통해여 프로그램의 비정상 종료를 막고 log를 남길 수 있음

 

2. 오류와 예외 클래스

 - 시스템 오류 (error) : 가상 머신에서 발생, 프로그래머가 처리 할 수 없음. ex) 동적 메모리를 다 사용한 경우, stack over flow 등

 - 예외 (Exception) : 프로그램에서 제어할 수 있는 오류. 읽으려는 파일이 없는 경우, 네트웍이나 소켓 연결 오류 등. 자바 프로그램에서는 예외에 대한 처리를 수행 함.

 

 

3. 예외 클래스

 - 모든 예외 클래스의 최상위 클래스는 Exception 클래스 

 

 

4. 예외 처리

4-1 try - catch - finally 문으로 예외 처리 하기

try{
  // 예외가 발생할 수 있는 코드 부분
} catch (처리할 예외 타입 e) {

  try블록 안에서 예외가 발생했을 때 수행되는 부분 (예외 내용 출력 등)	
} finally {
  예외 발생 여부와 상관 없이 항상 수행되는 부분
  리소스를 정리하는 코드를 주로 씀
}

1) try - catch - finally 사용 예제

package exception;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class ExceptionTest {
    
    public static void main(String[] args) {
        
        FileInputStream fis = null;
        
        try {
            fis = new FileInputStream("a.txt");
            
        } catch (FileNotFoundException e) { //1) try에서 실행 한 코드가 FileNotFoundException에 해당하면
            System.out.println(e); //2) 에러메세지 e를 출력한다.
           // return;
        
        } finally {
            try { //finally 구문이 실행될 때도 exception이 발생할 수 있으므로 try - catch문을 통해 처리한다.
                fis.close(); //리소스를 닫아준다.
                System.out.println("finally");
            } catch (Exception e) {
                System.out.println(e);
            }
        }
        System.out.println("end");
        
    }

}

4-2 try - with - resources 문으로 예외 처리 하기

 - 리소스를 자동으로 해체하도록 제공해주는 구문, finally를 사용하여 리소스를 해제할 때보다 코드의 가독성을 향상시킬 수 있음.

 - 해당 리소스가 AutoCloseable을 구현한 경우 close()를 명시적으로 호출하지 않아도 try{} 블록에서 오픈된 리소스는 정상적인 경우나 예외가 발생한 경우 모두 자동으로 close()가 호출 됨

 - 자바 7부터 제공 됨

 - FileInputStream의 경우 AutoCloseable을 구현 하고 있음 

1) try - with - resources 사용 예제

package exception;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class TryWithResourse {
    
    public static void main(String[] args) {
        
        //close를 하지 않아도 AutoCloseable을 해준다.
        try( FileInputStream fis = new FileInputStream("a.txt")) {
         
        } catch (FileNotFoundException e) {
            System.out.println(e);
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println(e);
        }
    }
}

2) AutoCloseable 인터페이스 사용하기

 - AutoCloseable 인터페이스를 구현한 클래스를 만들고 close()가 잘 호출되는지 확인.

 - AutoCloseable 구현 

package exception;

public class AutoCloseObj implements AutoCloseable {

    @Override
    public void close() throws Exception {
        System.out.println("close()가 호출되었습니다");
        
    }
    
    

}

 - AutoCloseable을 구현한 클래스 사용

package exception;

public class AutoCloseTest {

    public static void main(String[] args) {
        
        try (AutoCloseObj obj = new AutoCloseObj()){
            throw new Exception();
            
        } catch (Exception e) {
            
        }
     

    }

}

5. 다양한 예외 처리

 

5-1 예외 처리 미루기

 - throws를 사용하여 예외처리 미루기

 - try{} 블록으로 예외를 처리 하지 않고, 메서드 선언부에 throws를 추가

 - 예외가 발생한 메서드에서 예외 처리를 하지 않고 이 메서드를 호출한 곳에서 예외 처리를 한다는 의미

 - main() 에서 throws를 사용하면 가상머신에서 처리 됨.

 - throw : exception을 발생시키는 코드

 - throws : exception을 미루는 코드, 메서드를 호출(사용)하는 쪽에서 에러를 처리하게 함.

package exception;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class ThrowsException {
    
    //throws 통해 예외 처리 미루기 
    public Class loadClass(String fileName, String className) throws FileNotFoundException, ClassNotFoundException {
        FileInputStream fis = new FileInputStream(fileName);
        Class c = Class.forName(className);
        return c;
    }

    public static void main(String[] args) {
        
        
        //메서드를 호출한 곳에서 try catch를 통해 예외를 처리
        ThrowsException test = new ThrowsException();
        try {
            test.loadClass("b.txt", "java.lang.string");
            
        } catch (FileNotFoundException e) {
            System.out.println(e);
        } catch (ClassNotFoundException e) {
            System.out.println(e);
 
        }
    

    }

}

 

5-2 다중 예외 처리하기

 - 하나의 try{} 블록에서 여러 예외가 발생하는 경우 catch{} 블록 한 곳에서 처리하거나 여러 catch{} 블록으로 나누어 처리 할 수 있음

 - 가장 최상위 클래스인 Exception 클래스는 가장 마지막 블록에 위치해야함, 맨위나 중간에 위치하면, 미리 설정한 오류를 거치지 않고 Exception클래스가 해당 에러를 캐치함.

 

           //multi blocks를 통해 예외를 한번에 처리
            try {
                test.loadClass("a.txt", "java.lang.String");
            } catch (FileNotFoundException | ClassNotFoundException e) {
                e.printStackTrace();
            }
            
 
        System.out.println("end");
        ThrowsException test = new ThrowsException();
        try {
            test.loadClass("a.txt", "java.lang.String");
            
        } catch (FileNotFoundException e) {
            System.out.println(e);
        } catch (ClassNotFoundException e) {
            System.out.println(e);
            /*
             * 디폴트 exception : Exception이 최상위이기 때문에 
             * 모든 예외가 업캐스팅이 되고,
             * 이미 정의한 예외 이외의 error가 발생할 경우를 대비함.
             * 디폴트 exception은 맨 뒤에 처리해야 한다.
             */
        } catch(Exception e) { 
            System.out.println(e);
        }
        System.out.println("end");

5-3 사용자 정의 예외 

 - JDK에서 제공되는 예외 클래스 외에 사용자가 필요에 의해 예외 클래스를 정의하여 사용

 - 기존 JDK 클래스에서 상속받아 예외 클래스를 만듬

 - throw 키워드로 예외를 발생시킴 

 

1) Exception 클래스를 상속받아 Custome exception 정의  

package exception;

public class IDFormatException extends Exception {
    
    public IDFormatException(String message) { //String message : exception에 대한 메세지를 출력함.
        super(message);
    }

}

 

2) Custome한 exception을 사용한 예제

 - setting한 UserID가 null이거나 8자 이상 20자 이하가 아닐 경우 에러가 발생하도록 custome exception 사용

 - throw : exception을 발생시키는 코드

 - throws : exception을 미루는 코드, 메서드를 호출(사용)하는 쪽에서 에러를 처리하게 함.

package exception;

public class IDFormatTest {
    
    private String userID;
    
    public String getUserID() {
        return userID;
    }
    
    public void setUserID(String userID) throws IDFormatException {
        
        if (userID == null) {
            throw new IDFormatException("아이디는 null 일 수 없습니다");
        }
        else if (userID.length() < 8 || userID.length() > 20 ) {
            throw new IDFormatException("아이디는 8자 이상 20자 이하로 쓰세요");
        }
        
        this.userID = userID;
    }
    
    public static void main(String[] args) {
        
        IDFormatTest idTest = new IDFormatTest();
        
        String myId = null;
        
        //사용하는 쪽에서 exception처리 
        try {
            idTest.setUserID(myId);
        } catch (IDFormatException e) {
          System.out.println(e);
        }
        
        myId = "123456";
        try {
            idTest.setUserID(myId);
        } catch (IDFormatException e) {
          System.out.println(e);
        }
    }

}

3) 출력 결과 

 

'Java > Java 올인원 패키지' 카테고리의 다른 글

34. 직렬화 (Java)  (0) 2020.04.06
31. 입출력 스트림 (Java)  (0) 2020.03.24
29. 스트림 (Java)  (0) 2020.03.23
28. 람다식 (Java)  (0) 2020.03.23
27. 내부 클래스 (Java)  (0) 2020.03.21
댓글