13 예외처리

l  예외 처리

○ 프로그램 오류

프로그램이 실행 중 어떤 원인에 의해서 오작동을 하거나 비정상적으로 종료되는 경우

발생시점에 따라 구분

n  컴파일 에러 : 컴파일 시에 발생하는 에러

n  런타임 에러 : 실행 시에 발생하는 에러

n  논리적 에러 : 실행은 되지만, 의도와 다르게 동작하는 것

 

컴파일 에러

n  소스코드(*.java) –컴파일 -> 클래스 파일(*.class)

n  컴파일러가 기본적인 검사 수행하여 오류 알려줌

n  오류 수정하여 컴파일 마치면 클래스파일 생성되고 실행할 수 있음

 

런타임 에러

n  실행 도중 발생할 잠재적 오류까지 컴파일러가 검사할 수 없음

n  프로그램의 실행 도중 발생할 수 있는 모든 경우의 수 고려해 대비

n  에러와 예외 두 개가 있음

u  에러 : 메모리 부족이나 스택오버플로우 같이 일단 발생하면 복구할 수 없는 심각한 오류코드에 의해 수습 불가능

u  예외 : 발생하더라도 수습될 수 있는 비교적 덜 심각한 오류코드에 의해 수습 가능

n  예외는 적절한 코드로 비정상 종료 막을 수 있음

 

예외 클래스의 계층 구조

n  Exception 클래스와 그 자손들

u  외부의 영향으로 발생할 수 있는 것들

u  프로그램의 사용자들의 동작에 의해 발생하는 경우가 많음

u  FileNotFoundException, DataFormatException 같은 것들

n  RuntimeException 클래스와 그 자손들

u  프로그래머의 실수에 의해 발생 -> 자바의 프로그래밍 요소와 관련

u  IndexOutBoundsException, NullPointerException, ClassCastException, ArithmeticException

 

l  예외 처리하기 try – catch

예외처리 : 프로그램 실행 시 발생할 수 있는 예외 상황에 대한 대비 코드 짜는 것

try-catch

n  하나의 try블록에 여러 종류의 예외 처리할 수 있도록 하나 이상의 catch블록 올 수 있음

n  예외 종류랑 일치하는 catch문만 실행되고 나머지는 패스

n  일치하는 예외가 없으면 예외 처리 되지 않음

try{
	//예외가 발생할 가능성 있는 문장 넣기
}catch(Exception1 e1){
	// Exception1 발생 했을 경우, 이를 처리하기 위한 문장 넣기
}catch(Exception2 e2){
	// Exception2 발생 했을 경우, 이를 처리하기 위한 문장 넣기
} catch(ExceptionN eN){
	// ExceptionN 발생 했을 경우, 이를 처리하기 위한 문장 넣기
}
// 참조변수도 잘 바꿔줘야 함

 

try-catch문에서의 흐름

n  try블록에서 예외 발생했을 경우

(1)   발생한 예외가 일치하는 catch블럭 있는지 확인함

(2)   일치하는 catch블럭 찾으면 catch블럭 내 문장 수행 후 전체 try-catch문 빠져나가 다음 문장 실행

(3)   일치하는 catch블럭 못 찾으면 예외 처리 안됨

n  try블록에서 예외 발생하지 않았을 경우

(1)   catch블럭 거치지 않고 전체 try-catch문 빠져나가서 수행 계속함

n  try 블록에서 예외 발생하면 예외 발생 위치 이후 try블럭 안에 있는 문장 실행 한하므로 코드 범위 잘 선택해야 함

 

finally블럭

n  try-catch문에서 예외 발생 여부에 상관 없이 실행되어야 할 코드

try{
        // 예외 발생할 가능성 있는 문장들 
}catch(Exception1 e1){
        // 예외 처리 문장
}finally(
        // 예외 발생 여부에 상관없이 항상 수행되어야 하는 문장
        // try-catch문 맨 마지막에 위치
)

n  try 블록이나 catch 블록 문장 수행 중에 return문 만나도 finally블럭 문장 수행됨

 

예외 발생과 catch블럭

n  catch문 안에 괄호 속 예외와 try문에서 발생한 예외를 instanceof해서 catch블럭 찾음

n  Exception 클래스 타입은 모든 예외의 조상이므로 catch에 선언 안된 것은 이 블록으로 옴먼저 만나는 catch문이 일치하면 뒤에 catch문 실행 안되므로 젤 큰 예외 클래스는 마지막에 넣자

n  printStackTrace() & getMessage()

u  printStackTrace() : 예외 발생 당시의 호출스택에 있었던 메서드의 정보와 예외 메시지 화면에 출력함

u  getMessage() : 발생한 예외클래스의 인스턴스에 저장된 메시지 얻음

u  catch구문 괄호 안에 선언한 예외 참조변수로 메서드에 접근 가능

n  멀티 catch블럭

u  ‘ | ‘ 기호 이용해 한 catch문에 다중 예외 넣음

u  try {…} catch(Exception1 e1 | Exception2 e2){ … }

u  멀티 catch블록의 ‘ | ‘ 기호로 연결된 예외 클래스가 조상자식 관계면 컴파일 에러!조상만 선언해도 되는 것이니까

 

l  예외 발생시키기

키워드 throw

n  프로그래머가 고의로 예외 발생 시키기

(1)   연산자 new를 이용해 발생시키려는 예외 클래스 객체 만들기

(2)   키워드 throw를 이용해 예외 발생

n  Exception 인스턴스 생성할 때 생성자에 String 넣어주면 이 String Exception 인스턴스 메세지로 저장됨 -> getMessage()로 가져올 수 있음

 

RuntimeException과 그 자손 클래스

n  프로그래머가 실수해서 발생하는 것! -> 따로 굳이 예외 처리 안해도 됨

n  컴파일러가 예외처리 강제하지 않음 -> unchecked 예외

n  컴파일러가 예외 처리 확인하는 Exception 클래스들은 checked 예외

 

l  메서드에 예외 선언

메서드 선언부에 throws 사용해 메서드 내에서 발생할 수 있는 예외 적어줌

n  이 예외 뿐 아니라 자손 타입 예외도 발생할 수 있음

n  메서드 사용 시 메서드 선언부를 보고 어떤 예외들이 처리되어야 하는지 명시하는 역할

 

예외 처리 떠맡기기

n  메서드 사용하는 쪽에 이에 대한 처리를 강요하는 용도로 함

n  자신을 호출한 메서드에게 예외를 전달하여 예외처리를 떠맡기는 용도임

n  어느 한 곳에서 반드시 try-catch로 예외처리 해 주어야 함

 

l  자동 자원 반환 –try-with-resources

JDK 1.7부터 등장한 입출력 관련 클래스랑 사용하면 좋은 구문

n  입출력에 사용되는 클래스 중 사용한 후 꼭 닫아줘야 하는 것들을 닫아줌

n  자원 반환 해줘야 하는 것을 자원 반환해 줌

 

try-catch-finally 개선한 구문

n  finally 구문에서 try-catch문 넣어서 자원 반환하면 코드 복잡함

n  try 블록과 finally 블록 모두 예외 발생하면 try 블록 예외는 무시됨

n  이런 것들을 개선함

 

try-with-resources

n  try문의 관호에 객체 생성하는 문장 넣어주면 이 객체는 따로 close() 호출 안 해도 try블럭 벗어나면 자동으로 close() 호출함

n  AutoCloseale 인터페이스 구현한 객체를 자동으로 close() 호출할 수 있음

n  괄호 안에 두 문장 이상 넣을 경우 ‘ ; ‘로 구분

try(FileInputStream fis = new FileinputStream(“score.dat”) ; 
DataInputStream dis = new DataInputStream(fis)){
….
}catch(Exception1 e1){
}

 

억제된 예외

n  두 예외가 동시에 발생할 수 없음

è 실제 발생한 예외와 억제된 예외로 두 예외를 다룸

è 억제된 예외에 대한 정보는 실제 발생한 예외에 저장됨

n  억제된 예외와 관련된 메서드

u  void addSuppressed(Throwable exception) : 억제된 예외 추가

u  Throwable[ ] getSuppressed() : 억제된 에외(배열) 반환

 

l  사용자 정의 예외 만들기

Exception클래스 상속받아서 나의 예외 클래스 만들기 -> checked 예외가 되는 거지

n  Exception class String 받아 메시지 저장 가능 -> String 받는 생성자 추가해줘야 됨

RuntimeException 클래스 상속받아 만들면 unchecked 예외가 됨

 

l  예외 되던지기 (exception re-throwing)

한 메서드에서 발생한 예외가 여럿인 경우 -> 메서드 자신과 사용자 둘에서 양쪽에서 나눠 처리

n  몇 개는 try-catch문으로 메서드 내에서 자체로 처리

n  나머지는 선언부에 지정하여 호출된 메서드에서 처리

 

자신이 예외를 처리한 후 인위적으로 다시 발생시켜 호출 메서드에서 처리하도록 함

n  try-catch문을 사용해서 예외 처리 해주고 메서드 선언부에 발생할 예외를 throws에 지정해줌

n  반환값 있는 return문의 경우

u  catch블록에도 return으로 반환값 써줄 수 있음

u  catch문에서 예외 되던지기 해서 호출한 메서드로 예외 전달하면 return문 없어도 됨

n  finally 블록 내에서도 return문 사용할 수 있음! 결국 finally return문 값이 반환됨

 

l  연결된 예외(chained exception)

한 예외가 다른 예외 발생시키게 하는 것

n  원인 예외가 다른 예외를 발생시킴

n  예외를 하나의 큰 분류 예외로 묶어 다루되, 조상관계로 만들지 않는 방법

n  checked 예외를 unchecked 예외로 바꿀 때도 씀

 

initCause()

n  Throwable 클래스에 정의되어 있는 메서드들

□ Throwable initCause() (Throwable cause) : 지정한 예외를 원인 예외로 등록

□ Throwable getCause() : 원인 예외를 반환

■ 예외 생성한 뒤에 initCause 예외를 다른 예외의 원인 예외로 등록 후 throw로 던짐

■ 예외를 큰 분류로 묶어 다룰 수 있음

 

○ RuntimeException(Throwable cause)

■ 원인 예외를 등록하는 생성자

■ checked 예외를 unchecked 예외로 바꾸어 예외 처리를 선택적으로 함

■ RuntimeException으로 Exception 예외를 감싸는 것

 

+ Recent posts