-
728x90
예외
프로그램 에러, 오류 - 오작동, 비정상적인 종료
컴파일 에러 - 컴파일시 에러
런타임 에러 - 실행시 에러
논리적 에러 - 실행은 되지만, 의도와 다르게 동작에러 - 코드로 수습 불가한 심각한 오류
예외 - 코드로 수습 가능한 미약한 오류예외 클래스 계층 구조
Exception, Error클래스 역시 Object 클래스의 자손이다.
예외 클래스 계층도 모든 예외의 최고 조상은 Exception클래스이다.
Exception 클래스와 RuntimeException 중심의 상속계층도 Exception 클래스들 - 사용자 실수와 같은 외적인 요인에 의해 발생
RuntimeException 클래스들 - 프로그래머 실수RuntimeException
1 . 배열의 범위를 벗어남 : ArrayIndexOutOfBoundsException
2. 값이 null인 참조변수의 멤버를 호출하려 함 : NullPointerException
3. 클래스간의 형변화 잘못함 : ClassCasException
4. 정수를 0으로 나누려고함 : ArithmeticExceptionException
1. 존재하지 않은 파일의 이름을 입력 : FileNotFoundException
2. 실수로 클래스의 이름을 잘못 적음 : ClassNotFoundException
3. 입력한 데이터 형식이 잘못됨 : DataFormatException예외처리 ( try - catch )
try - catch : 프로그램의 비정상 종료를 막고, 정상적인 실행 상태를 유지할 수 있도록 하는 것이다
try - catch 구조
try { // 예외가 발생할 가능성이 있는 문장 } catch (Exception e1) { // Exception 발생시 처리하기 위한 문자 }
- Exception은 모든 예외 클래스의 조상이므로, 다른 예외여도 처리가 가능
catch 블럭 내에 또 하나의 try - catch문이 포함된 경우, 같은 이름의 참조변수를 하면 안된다.
try { try { } catch ( Exception e) { } } catch (Exception e1) { try { } catch ( Exception e) { } // e가 중복됨 e이름을 e1 같이 바꿔야함 }
try문에서 예외가 발생하면 그 밑의 코드들은 실행 시키지 않고 블럭을 벗어난다
printStackTrace() , getMessage()
printStackTrace() : 예와시 당시 호출스택에 있던 메서드의 정보와 예외 메세지를 출력
getMessage() : 예외 클래스의 인스턴스에 저장된 메세지를 얻을 수 있다.catch() 블럭 괄호에 선언된 참조변수를 통해 이 인스턴스에 접근 가능
try { /* 내용 */ } catch ( Exception ae ) { ae.printStaceTrace(); System.out.println(ae.getMessage() ); }
멀티 catch 블럭
'|' 기호를 통해 여러 catch 블럭을 하나의 블럭으로 나타낼 수 있다 ( 예외 클래스가 조상, 자손 관계이면 안된다. )
참조변수 e 로 멀티 catch블럭에 '|' 기호로 연결된 예외 클래스들의 공통 분모의 조상 예외 클래에 선언된 멤버만 사용할 수 있다.
try { } catch (ExceptionA | ExceptionB e ) { }
예외 발생시키기
키워드 throw를 사용해 고의로 예외를 발생시킬 수 있다.
try { throw new Exception(); } catch ( Exception e ) { e.printStackTrace(); // e.getMessage() 도 가능 }
Exception 클래스들은 컴파일도 되지 않아 예외 처리를 해야하는 'checked예외' 라고 부른다.
RuntimeException 클래스들은 컴파일은 되지만 실행이 되지 않는거라 예외처리를 하지 않아도 되는 'unchecked예외' 라고 부른다.
-> 그래서 RuntimeException 클래스들은 예외 처리를 필수로 하는 곳에만 해주면 된다.
메서드에 예외 선언하기
메서드의 선언부에 throws를 사용하면 된다.
void method() throws Exception { // 메서드의 내용 }
모든 예외의 최고 조사인 Exception을 이렇게 메서드에 선언하면 모든 종류의 예외가 발생할 수 있으며, 자손타입의 예외까지 발생할 수 있어서, 상속도 고려해야한다.
이렇게 메서드에 예외 처리를 해줌으로써, 이 메서드를 사용하기 위해서는 어떠한 예외 처리를 해줘야 하는지 미리 예측이 가능해서 더욱 견고한 코드를 작성할 수 있다. (JAVA.api 문서 참조 -> 메서드에 throws Exception 이런식으로 적혀있는데 그것을 예외처리해주면 됨 )
finally 블럭
구조 예시
try { // 예외가 발생할 가능성이 있는 문장 } catch (Exception e1) { // Exception 발생시 처리하기 위한 문자 } finally { // 예외 발생 여부없이 수행되야 하는 문장 }
코드 예시
try { startInstall(); copyFiles(); return; // 리턴문을 만나도 finally 문은 실행된다 } catch (Exception e1) { e1.printStackTrace(); } finally { deleteFiles(); }
try, catch, finally 모든 블럭에서 return문 가능하고 try -> catch -> finally 순으로 진행된다.
try - catch - finally 문에서 try나 catch문에서 return이 발생하면 finally문을 실행하고 메소드를 닫는다. ( try에서 return 발생시 바로 finally 문으로 간다 )
try - with - resources문
주로 입출력에서 사용되는 클래스 중에서는 사용 후 꼭 닫아줘야하는 것들이 있는데, 그들을 위한다
try { fis = new FileInputStream("score.dat"); dis = new DataInputStream(fis); } catch ( IOException ie) { ie.printStackTrace(); } finally { dis.close(); } // 하지만 여기서 close에서도 예외가 발생 가능 // ( ) 안에 두문장 이상은 ; 로 구분 try ( FileInputStream fis = new FileInputStream("score.dat"); DataInputStream dis = new DataInputStream(fis) ) { while(true) { /* */ } } catch ( IOException ie) { ie.printStackTrace(); }
try - with - resources문의 괄호 안에 객체를 생성해서 넣으면 close() 호출하지 않아도 try 블럭을 벗어나면 자동적으로 호출한다.
Throwable에 억제된 예외와 관련된 메서드
void addSuppressed(Throwable exception) 억제된 예외를 추가 Throwable[] getSuppressed() 억제된 예외(배열)를 반환
사용자정의 예외 만들기
예전에는 Exception 클래스를 상속받아 'checked 예외' 만들었지만, 요즘은 RuntimeException 클래스를 상속받아 'unchecked 예외'를 만드는것을 지향한다
예시
class newException { public static void main(String[] args) { try { startInstall(); } catch (SpaceException e) { /* */ } catch (MemoryException me ) { /* */ } finally { deleteFile(); } } } static void startInstall() throws SpaceException, MemoryException { if(!enoughSpace()) throw new SpaceException(" "); if(!enoughMemory()) throw new MemoryException(" "); } static boolean enoughSpace() { } static boolean enoughMemory() { } class SpaceException extends Exception { SpaceException(String msg) { super(msg); } } class MemoryException extends Exception { MemoryException(String msg) { super(msg); } }
예외 되던지기
이 방법은 하나의 예외에 대해서 예외가 발생한 메서드와 이를 호출한 메서드 양쪽 모두에서 처리를 해줘야 할 작업이 있을 때 사용된다 ( 주의할 점은 try-catch문을 사용해 예외처리를 해줌과 동시에 메서드의 선언부에 발생한 예외를 throws에 지정해야함 )
class Exception { public static void main(String[] args) { try { method1(); } catch(exception e) { System.out.println("main에서 예외 처리"); } } static void method1() throws Exception { try { throw new Exception(); } catch (Exception e) { System.out.println("method1에서 예외 처리"); throw e; } } } // 반환값이 있는 return문 같은 경우에는 catch 블럭에서도 return문이 있어야 한다 static void method1() throws Exception { try { System.out.println("method1호출"); return 0; // 현재 실행중인 메소드 종료 } catch (Exception e) { e.printStackTrace(); // return 1; catch문에서도 return문 필요 throw new Exception; // return문 대신 예외를 호출한 메서드로 전달 } finally { System.out.println("finally"); } }
연결된 예외
하나의 예외가 다른 예외를 발생 시킬 수 있다. ( a -> b 발생 : a를 b의 '원인 예외' 라고 부름 )
try { startInstall(); } catch ( SpaceException e ) { InstallException ie = new InstallException(" "); // 예외 생성 ie.initCause(e); // InstallException의 원인예외를 SpaceException으로지정 throw ie; // InstallException 발생 시킴 }
InstallException 생성 -> initCause로 SpaceException를 InstallException의 원인 예외로 등록 -> throw로 예외를 던짐
initCause() 는 원인 예외로 등록할 수 있는 메소드다
또한, Exception의 조상인 Throwable 클래스에 정의 되어있어서 모든 예외에 적용이 가능하다.
Throwable initCause(Throwable cause) // 지정한 예외를 원인예외로 등록 Throwable getCause(). // 원인 예외를 반환
원인 예외로 등록해서 다시 예외를 발생 시키는 이유
1. 여러가지 예외를 하나의 큰 분류의 예외로 묶어서 다루기 위해
2. checked 예외 -> unchecked 예외로 바꿀수 있도록 하기 위해2번의 예시 코드
static void startInstall() throws SpaceException, MemoryException { if(!enoughSpace()) throw new SpaceException(" "); if(!enoughMemory()) throw new MemoryException(" "); } // 바꾸면 static void startInstall() throws SpaceException { if(!enoughSpace()) throw new SpaceException(" "); if(!enoughMemory()) throw new RuntimeEeception(new MemoryException(" ")); }
RuntimExcception 으로 감싸버렸기에 unchecked 예외가 되었다.
initCause() 대신에 RuntimExcception의 생성자를 사용했다
RuntimExcception(Throwable cause) 는 원인 예외를 등록하는 생성자다.
'자바' 카테고리의 다른 글
[자바] 정규형 패턴 (0) 2022.07.15 [자바] JAVA.LANG패키지와 유용한 클래스 (0) 2022.07.15 [자바] 객체지향(2) - 2 (0) 2022.07.13 [자바] 객체지향(2) - 1 ( 패키지 ) (0) 2022.07.09 [자바] 객체지향(1) (0) 2022.07.07