에러 : 컴퓨터 하드웨어의 오작동 또는 고장으로 인해 응용 프로그램 실행 오류가 발생하는 것
예외 : 에러 이외에 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인해 발생하는 프로그램 오류
→ 개발자가 해결할 수 있는 오류 ( == 오류 발생 시 차선책을 선택할 수 있는)
에러나 예외가 발생되면 프로그램이 종료됨
→ 예외는 예외처리를 통해 프로그램이 종료되지 않게, 정상 실행 상태를 유지하게 만들 수 있음
자바는 예외가 발생할 가능성이 높은 코드를 컴파일할 때 예외 처리 유무를 확인함
→ 만약 예외 처리 코드가 없다면 컴파일이 안됨
→ 하지만 모든 예외에 대해서 확인하는 것은 아님
자바에서는 예외를 클래스로 관리
JVM은 프로그램을 실행하는 도중에 예외가 발생하면 해당 예외 클래스로 객체를 생성
→ 예외 처리 코드에서 예외 객체를 이용할 수 있도록 해줌
모든 예외 클래스는 java.lang.Exception 클래스를 상속받음
예외의 종류:
- 일반예외 exception : 컴파일 전에 체크
프로그램 실행 시 예외가 발생할 가능성이 높기 때문에 자바 소스코드를 컴파일하는 과정에서
해당 예외 처리 코드가 있는지 검사 → 없다면 컴파일 오류 발생
== 예외처리를 해주지 않으면 실행 자체가 불가능! - 실행예외 runtime exception : 실행할 때 체크
실행 시 예측할 수 없이 갑자기 발생하기 때문에 컴파일하는 과정에서 예외 처리 코드가 있는지 검사하지 않음
→ 실행 중 실행예외가 생기면 프로그램 강제 종료!
일반예외 종류 :
- InterruptedException
- ClassNotFoundException
- IOException
- FileNotFoundException
- CloneNotSupportedException
실행예외 종류 :
- NullPointException
객체 참조가 없는 상태, 즉 null 값을 갖는 참조변수로 객체 접근 연산자인 . 를 사용했을 때 발생
== 객체가 없는 상태에서 객체를 사용하려해서 예외 발생 - ArrayIndexOutOfBoundsException
배열에서 인덱스 범위를 초과할 경우 - NumberFormatException
매개값인 문자열이 숫자로 변활될 수 없는 문자가 포함되어 있는 경우 - ClassCastException
타입 변환은 상위-하위 클래스 간에 발생하고 구현 클래스와 인터페이스 간에도 발생
이러한 관계가 아니라면 클래스는 다른 타입으로 변환할 수 없기 때문에 발생
== 다운캐스팅이 불가능한 상황에서 다운캐스팅을 시도할 때 발생 - ArithmeticException
연산 자체가 불가능할 때 발생(ex 분모가 0일 때)
예외 처리 구문이 있다면 JVM은 적절히 예외가 처리되었다고 판단하기 때문에 강제종료 되지 않음
심지어 구문 내에 어떤한 코드도 없어도 예외가 처리된 것으로 간주함
예외 처리
try - catch - finally 블록
생성자 내부와 메서드 내부에서 작성되어 일반 예외와 실행 예외가 발생할 경우, 예외 처리를 할 수 있도록 해줌
try {
// 일반예외, 실행예외 발생 가능 코드
} catch (예외클래스명 참조변수명) { //다중catch가능
// 예외가 발생했을 때 처리
} finally { //생략가능
// 예외 발생과 상관없이 무조건 실행
}
예외 전가
throws 키워드
메소드 선언부 끝에 작성되어 메서드 작성되어 메서드에서 처리하지 않은 예외를 호출한 곳으로 떠넘기는 역할을 함
→ 자신을 호출한 지점으로 예외를 전가시킴
→ 예외 처리의 의무를 호출한 메서드가 가지게 됨!
리턴타입 메서드명(입력매개변수) throws 예외클래스명 {
//예외발생코드
}
사용자 정의 예외 클래스
생성방법
- 예외클래스 직접 정의
- 작성한 예외클래스를 이용해 객체 생성
- 고려해야하는 상황에 예외 객체를 던짐(throws)
▼ 예외를 해당 메서드 안에서 직접 처리
void abc(int age) {
try {
if (age >= 0)
System.out.println("정상값 출력");
else
throws new MyException();
} catch (MyException e) {
System.out.println("예외처리");
}
}
void def() {
abc(-2);
}
▼ 예외를 상위 메서드로 전가하여 예외 처리
void abc(int age) throws MyException {
if (age >= 0)
System.out.println("정상값 출력");
else
throws new MyException();
}
void def() {
abc(-2);
try {
abc(-2);
} catch (MyException e) {
System.out.println("예외처리");
}
}
예외클래스 메서드
▶ getMessage()
예외객체에 저장된 메세지를 반환
이 메시지에는 예외가 발생한 원인에 대한 간단한 설명을 포함하고 있음
예외 클래스의 생성자에서 설정할 수 있음
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("예외 메시지: " + e.getMessage());
}
//Exception message: / by zero
public class CustomExceptionExample {
public static void main(String[] args) {
try {
throw new Exception("Custom error message");
} catch (Exception e) {
System.out.println("Exception message: " + e.getMessage());
}
}
}
//Exception message: Custom error message
▶ printStackTrace()
예외가 발생했을 때 호출 스택(Call Stack)의 정보를 출력
예외가 발생한 시점의 메서드 호출 경로를 추적하여, 디버깅 시 매우 유용한 정보를 제공
public class ExceptionPrintStackTraceExample {
public static void main(String[] args) {
try {
int[] numbers = {1, 2, 3};
System.out.println(numbers[5]); // ArrayIndexOutOfBoundsException 발생
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
}
}
//java.lang.ArrayIndexOutOfBoundsException: 5
// at ExceptionPrintStackTraceExample.main(ExceptionPrintStackTraceExample.java:5)
예시
public class ExceptionTest {
public static void main(String[] args) {
// print(-5);
// 컴파일 오류
// print 메서드가 throws절로 정의되어 있어서
// 그 예외를 처리하지 않으면 컴파일이 안된다.
// 어캐해야하는데
// throws절로 처리하기
// try~catch로 처리하기
try {
print(-5);
} catch (Exception e) {
} // 이런방식으로
}
private static void print(int count) throws Exception {
if (count < 0) throw new Exception("음수는 안돼욧");
for (int i = 0; i < count; i++) {
System.out.println("hello");
}
}
}
▼ try catch
public class ExceptionTest {
public static void main(String[] args) {
methodA();
}
private static void methodA() {
try {
methodB();
} catch (Exception e) {
}
}
private static void methodB() throws Exception {
int random = (int) (Math.random() * 10);
if (random % 2 == 0)
throw new Exception();
}
}
▼ throws
public class ExceptionTest {
public static void main(String[] args) throws Exception {
methodA();
}
private static void methodA() throws Exception {
methodB();
}
private static void methodB() throws Exception {
int random = (int) (Math.random() * 10);
if (random % 2 == 0)
throw new Exception();
}
}
▼ 사용자 정의
public class ExceptionTest {
public static void main(String[] args) {
try {
print(-5);
} catch (Exception e) { //Exception 객체를 참조하는 e
System.out.println(e.getMessage());
}
}
private static void print(int count) throws Exception {
if (count < 0) throw new Exception("음수는 안돼욧"); //Exception 객체생성
for (int i = 0; i < count; i++) {
System.out.println("hello");
}
}
}
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class ExceptionTest {
public static void main(String[] args) throws Exception {
try {
FileReader fr = new FileReader("list.txt");
// 애초에 FileReader의 생성자가 throw절로 정의되어있어서
// 이것을 호출하는 부분에도 예외처리를 해주어야한다
BufferedReader br = new BufferedReader(fr);
String line = br.readLine();
while (line != null) {
System.out.println(line);
line = br.readLine();
}
} catch (FileNotFoundException e) {
System.out.println("그런 파일은 없어용");
} catch (IOException e) {
}
}
}
public class ExceptionTest {
public static void main(String[] args) {
try {
System.out.println("start");
print(5);
System.out.println("after");
} catch (Exception e) {
System.out.println("catch");
System.out.println(e.getMessage());
} finally {
System.out.println("finally");
}
}
private static void print(int count) throws Exception {
if (count < 0)
throw new Exception("음수는 안돼욧");
System.out.println("after if");
for (int i = 0; i < count; i++) {
System.out.println("hello");
}
}
}
▼ RuntimeException
public class ExceptionTest {
public static void main(String[] args) {
methodA();
}
private static void methodA() {
try {
methodB();
} catch (RuntimeException e) {
}
}
private static void methodB() throws RuntimeException {
int random = (int) (Math.random() * 10);
if (random % 2 == 0)
throw new RuntimeException();
}
}
'Language > Studying' 카테고리의 다른 글
[JS] 1급객체와 콜백함수 (0) | 2024.07.24 |
---|---|
[Java] Compile-time과 Run-time (0) | 2024.07.19 |
[Java] Overload와 Override (feat. 다형성) (0) | 2024.07.17 |
[Java] Java API (0) | 2024.07.17 |
[Java] Heap 영역과 Stack 영역 (feat. 동적할당, 정적할당) (0) | 2024.07.16 |