프로그램 오류(에러)
: 프로그램이 실행 중 오작동을 하거나 비정상적으로 종료되는 경우를 초래하는 원인.
- 컴파일 에러(compile-time error) : 컴파일 할 때 발생하는 에러.
- 런타임 에러(runtime error) : 프로그램 실행 도중에 발생하는 에러.
- 논리적 에러(logical error) : 컴파일, 실행에는 이상없지만 의도와 다르게 동작하는 것.
에러(error)와 예외(exception)
: 자바에서 실행시 발행할 수 있는 프로그램 오류의 유형.
- 에러(error) : 발생하면 프로그램 코드에 의해서 수습될 수 없는 심각한 오류.
프로그램의 비정상적인 종료를 막을 수 없다.
ex) OutOfMemoryError(메모리부족), StackOverflowError(스택오버플로우)...
- 예외(exception) : 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류.
발생하더라도 이에 적절한 코드를 미리 작성해놓으면 프로그램의 비정상적인 종료를 막을 수 있다.
예외 클래스의 계층구조
- 자바에서 실행 시 발생할 수 있는 오류(Exception과 Error)를 클래스로 정의.
- 모든 클래스의 조상은 Object이므로 Exception과 Error클래스도 Object클래스의 자손들이다.
- 모든 예외의 최고 조상은 Exception클래스이다.
-RuntimeException클래스와 그 자손 클래스들 : 주로 프로그래머의 실수에 의해서 발생될 수 있는 예외들.
ex) 배열의 범위를 벗어남(ArrayIndexOutOfBoundsException), null에서 참조변수의 멤버를 호출(NullPointException), 클래스간의 형변환을 잘못함(ClassCastException), 정수를 0으로 나누려고 함(ArithmeticException) 등등..
- Exception클래스와 그 자손 클래스들 : 주로 외부의 영행을 발생할 수 있는 예외들. 프로그램 사용자들의 동작에 의해서 발생하는 경우가 많다.
ex) 존재하지 않은 파일의 이름 입력(FileNotFoundException), 클래스의 이름을 잘못적기(classNotFoundException), 입력한 데이터 형식이 잘못된 경우(DataFormatException) 등등...
예외처리하기 - try-catch문
- 프로그램 실행 중 발생하는 에러는 어쩔 수 없지만, 예외는 프로그래머가 미리 처리를 해주어야한다.
- 예외처리의 정의 : 프로그램 실행 시 발생할 수 있는 예외에 대비한 코드를 작성하는 것.
- 예외처리의 목적 : 예외의 발생으로 인한 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지할 수 있도록 하는 것.
- 처리되지 못한 예외는 JVM의 '예외처리기'가 받아서 예외의 원인을 화면에 출력한다.
(* 예외처리기 : 예외 처리기는 예외가 발생하면 예외 객체를 생성시키고 예외가 발생된 메소드에서 ERROR 를 출력하고, 그 메소드를 호출한 메소드에게 예외를 반환한다. 출처 : https://herojune.tistory.com/2)
/* try-catch문 예시 */
try {
// 예외가 발생할 가능성이 있는 문장들을 넣는다.
} catch (Exception1 e1) {
// Exception1이 발생했을 경우, 이를 처리하기 위한 문장을 적는다.
} catch (Exception2 e2) {
// Exception2이 발생했을 경우, 이를 처리하기 위한 문장을 적는다.
}
- 하나의 try블럭 다음에는 여러 종류의 예외를 처리할 수 있도록 하나 이상의 catch블럭이 올 수 있으며, 그 중 발생한 예외의 종류와 일치하는 단 한개의 catch블럭만 수행된다.
- 발생한 예외의 종류와 일치하는 catch블럭이 없으면 예외는 처리되지 않는다.
- if문과 달리, try블럭이나 catch블럭 내에 포함된 문장이 하나뿐이어도 괄호 { }를 생략할 수 없다.
( catch(Exception e) ~~예외처리 코드 --> 이렇게 작성 불가 )
class ExceptionEx1 {
public static void main(String[] args) {
try {
try { } catch (Exception e) { }
} catch (Exception e) {
// 에러. 변수 e가 중복 선언되었다.
try { } catch (Exception e) { }
}
}
}
- 하나의 메서드 내에 여러 개의 try-catch문이 사용될 수 있으며, try블럭 또는 catch블럭에 또 다른 try-catch문이 포함될 수 있다.
- catch블럭내에 또 try-catch문이 포함될 경우 같은 이름의 참조변수를 사용하면 안된다. 각 catch블럭에 선언된 두 참조변수의 영역이 서로 겹치므로 다른 이름을 사용해야한다.
try-catch문에서의 흐름
예외 발생 유무에 따라 문장의 실행순서가 다르다.
- try블럭 내에서 예외가 발생한 경우
1. 발생한 예외와 일치하는 catch블럭이 있는지 확인한다.
2. 일치하는 catch블럭을 찾게 되면, 그 catch블럭 내에 문장들을 수행하고 전체 try-catch문을 빠져나가서 그 다음 문장을 수행 한다.
3. 만일 일치하는 catch블럭을 찾지 못하면, 예외는 처리되지 못한다.
-try블럭 내에서 예외가 발생하지 않은 경우
catch블럭을 거치지 않고 전체 try-catch문을 빠져나가서 수행을 계속한다 .
Class ExceptionEx {
public static void main(String args[]) {
System.out.println(1);
System.out.println(2);
try {
System.out.println(3);
System.out.println(0/0); // 0으로 나눠서 고의로 에러 발생 시킴.
// 에러가 발생한 이후에는 catch블럭의 코드가 실행되므로, 해당코드는 실행되지 않는다.
System.out.println(4);
} catch (Exception e) {
System.out.println(5);
} // try-catch의 끝
System.out.println(6);
}
}
/*
실행결과
1
2
3
5
6
*/
* try블럭에서 예외가 발생하면, 예외가 발생한 위치 이후에 있는 try블럭의 문장들은 수행되지 않으므로, try블럭에 포함시킬 코드의 범위를 잘 선택해야한다.
예외의 발생과 catch블럭
- catch블럭의 괄호() 내에는 처리하고자 하는 예외와 같은 타입의 참조변수 하나를 선언해야한다.
- 예외가 발생하면, 발생한 예외에 해당하는 클래스의 인스턴스가 만들어진다.
- 첫 번째 catch블럭부터 차례로 내려가면서 catch블럭의 괄호()내에 선언된 참조변수의 종류와 생성된 예외클래스의 인스턴스에 instanceof연산자를 이용해서 검사결과가 true가 될 때 까지 계속 검사한다.
- true가 나오면 블럭안에 있는 문장들을 모두 수행한 후 try-catch문을 빠져나가고 예외가 처리되지만, true인 블럭이 하나도 없으면 예외는 처리되지 않는다.
- 모든 예외 클래스는 Exception클래스의 자손이므로, catch블럭의 괄호()에 Exception클래스 타입의 참조변수를 선언해 놓으면 어떤 종류의 예외라도 이 catch블럭에서 처리된다.
printStackTrace()와 getMessage()
- 예외가 발생했을 때 생성되는 예외 클래스의 인스턴스에는 발생한 예외에 대한 정보가 담겨져 있는데 아래 메소드 호출을 통해 예외의 발생원인을 확인 할 수 있다.
- printStackTrace() : 예외발생 당시의 호출스택(Call Stack)에 있었던 메서드의 정보와 예외메시지를 화면에 출력한다.
- getMessage() : 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있다.
- printStackTrace(PrintStream s) ,printStackTrace(PrintWriter s)를 사용하면 발생한 예외에 대한 정보를 파일에 저장할 수도 있다.
멀티 catch블럭
- 멀티 catch 블럭은 JDK1.7부터 여러 catch블럭을 '|' 기호를 이용해서, 하나의 catch블럭으로 합치는 것을 말한다.
- 멀티 catch 블럭을 이용하면 중복된 코드를 줄일 수 있다.
- '|' 기호로 연결할 수 있는 예외 클래스의 개수에는 제한이 없다.
try {
...
} catch (ParentException | ChildException e ) { // 에러! 조상과 자식의 관계
e.printStackTrace();
} catch (ExceptionA | ExeptionB e) {
e.methodA(); // 에러! 조상클래스가 아닌 ExceptionA에만 선언된 메소드는 호출 불가
}
* 멀티 catch 사용시 주의할 점
- '|' 기호로 연결된 예외클래스가 조상과 자손의 관계에 있다면 컴파일 에러가 발생한다. 이유는 자손의클래스와 같이 사용하면 그냥 조상클래스만 써주는 것과 똑같기 때문이다. 불필요한 코드는 제거하라는 의미에서 에러가 발생한다.
- 멀티 catch블럭 내에서는 실제로 어떤 예외가 발생한 것인지 알 수 없기 때문에 '|' 기호로 연결된 예외 클래스들의 공통 분모인 조상 예외. 클래스에 선언된 멤버만 사용할 수 있다.
- 멀티 catch블럭에 선언된 참조변수 e는 상수이므로 값을 변경할 수 없다. 이유는 여러 catch블럭이 하나의 참조변수를 공유하기 때문이다.
'개발 공부 > Java & Spring' 카테고리의 다른 글
9. Math클래스 (0) | 2022.12.06 |
---|---|
8. StringBuffer 클래스와 StringBuilder 클래스 (0) | 2022.12.06 |
6. 내부 클래스(inner class) (1) | 2022.11.06 |
5. 제어자(modifier) (0) | 2022.10.24 |
4. package와 import (0) | 2022.10.23 |