프로그램 오류
- 컴파일 에러 : 소스코드 내의 오타나 잘못된 구문, 자료형 체크 등 기본적인 검사를 수행하는 과정에서 에러
- 런타임 에러 : 메모리 부족, 스택 오버플로우 등 코드에 의해서 수습될 수 없는 심각한 오류(error)와 코드에 의해 수습될 수 있는 미약한 오류(Exception)으로 구분된다.
- 논리적 에러 : 실행은 되지만 의도와 다르게 동작하는 경우를 말한다.
계층도를 보면 RuntimeException은 주로 프로그래머의 실수에 의해 발생하는 경우가 많다.
Exception 클래스들은 FileNotFoundException, DataFormatException 등 외부의 영향으로 주로 발생한다.
try-catch 문
프로그램 실행 시 예기치 못한 예외의 발생에 대비한 코드를 작성한다.
처리되지 못한 코드는 JVM의 UncaughtExceptionHandler가 받아 화면에 출력한다.
예외가 발생하면, 예외 클래스의 인스턴스가 생성되고
'instanceOf' 연산자를 사용해 catch 블럭 중 인스턴스의 검사 결과가 true인 블럭을 실행한다.
검사 결과가 true인 블럭이 없다면 예외는 처리되지 않는다.
발생한 예외에 대한 정보를 얻기 위해선 아래 두 메소드를 사용한다.
- printStackTrace() : JVM의 호출 스택에 있었던 메소드의 정보와 예외 메세지를 출력
- getMessage() : 발생한 예외 클래스의 인스턴스에 저장된 메세지를 얻는다.
그리고 아래와 같이, '멀티 catch블럭'을 사용해 여러가지 catch 블럭을 하나의 블럭으로 합칠 수 있다.
try{
// Exception
} catch (ExceptionA | ExceptionB e){
e.printStackTrace();
}
만약 코드 상에서 멀티 블럭으로 사용하는 여러가지 예외 클래스가 상속 관계에 있다면 에러가 발생한다.
메서드에 예외 선언하기
메서드의 선언부에 예외를 선언함으로써
메서드의 선언부를 보고, 어떤 예외들을 처리해야 하는지 쉽게 알 수 있다.
void method() throws Exception1, Exception2, ... ExceptionN {
// 메소드 사용
}
함수 호출 시 예외 처리 방법을 비교해보자
public static void main(String[] args){
File f = createFile(args[0]);
}
static File createFile(String fileName){
try{
if(fileName == null || fileName.equals(""))
throw new Exception("파일 이름이 유효하지 않습니다. ");
} catch(Exception e){
e.printStackTrace();
} finally {
File f = new File(fileName);
createNewFile(f);
return f;
}
}
static void createNewFile(File f){
try{
f.createNewFile();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args){
try{
File f = createFile(args[0]);
} catch(Exception e){
e.printStackTrace();
}
}
static File createFile(String fileName) throws Exception{
if(fileName == null || fileName.equals(""))
throw new Exception("파일 이름이 유효하지 않습니다. ");
File f = new File(fileName);
createNewFile(f);
return f;
}
두 메서드 모두 적합한 예외처리 방법이며,
단 위 코드의 경우 main 메서드에서는 예외가 발생한 사실을 모른다.
두 번째 경우처럼 fileName을 반환받아 main함수에서 사용해야 하는 경우 예외를 메서드에 선언해서 호출한 main 메서드 안에서 catch하는 것이 바람직하다.
finally 블럭
위의 코드에서 보았다시피,
finally 블럭은 예외의 발생 여부와 상관없이 실행된다.
tyr, catch블럭에서 return문을 만나도 마찬가지이다.
이렇게, 무조건 실행되는 finally블럭에서 예외가 생길 경우를 대비해
try-with-resouces 문을 사용할 수 있다.
try문에서 객체를 생성하면 try문을 벗어나는 순간 자동으로 close()가 호출된다.
try(FileInputStream fis = new FileInputStream("score.dat");
DataInputStream dis = new DataInputStream(fis)){
//
} catch (IOException e) {
e.printStackTrace();
}
예외 되던지기 (exception re-throwing)
public static void main(String[] args){
try{
method();
} catch (Exception e){
e.printStackTrace();
}
}
static void method() throws Exception {
try{
throw new Exception();
} catch (Exception e){
e.printStackTrace();
throw e;
}
}
catch문에서 예외를 throw하여,
하나의 예외에 대해서 예외가 발생한 메서드와 이를 호출한 메서드의 양쪽 모두에서 처리해주어야하는 경우
위와 같이 예외 되던지기를 수행할 수 있다.
이 경우 메소드의 선언부에 예외를 선언해주어야 한다.
'Langauge > Java' 카테고리의 다른 글
Java의 정석 Chapter10. 날짜와 시간 & 형식화 / Chapter11. 컬렉션 프레임워크 (0) | 2022.03.29 |
---|---|
Java의 정석 Chapter9. java.lang 패키지와 유용한 클래스 (0) | 2022.03.21 |
Java InputStream에서 File 객체로 변환하기 (0) | 2022.03.21 |
Java의 정석 Chapter7.객체지향 프로그래밍2 (0) | 2022.03.13 |
Java의 정석 Chapter6. 객체지향 프로그래밍 (0) | 2022.03.13 |