이전 내용
[java] 인터페이스 상속, 중첩 클래스, 중첩 인터페이스
이전 내용 [java] instanceof, 인터페이스, 구현 클래스이전 내용 [java] 추상 클래스, 추상 메소드이전 내용 [java] 클래스의 타입 변환, 다형성이전 내용 [java] 접근 제한자, 클래스 상속이전 내용 [ja
puppy-foot-it.tistory.com
예외
◆ 예외(Exception)
사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인해 발생하는 프로그램 오류.
[예외 vs 오류]
- 예외:
예외는 예외가 발생하면 예외 처리를 통해 프로그램을 종료하지 않고 정상 실행 상태가 유지되도록 할 수 있음.
- 오류:
컴퓨터 하드웨어의 오동작 또는 고장으로 인해 응용프로그램 실행 오류가 발생하는 것. 발생 시 프로그램 종료 됨.
[예외의 두 가지 종류]
- 일반 예외(컴파일러 체크 예외) : 프로그램 실행 시 예외가 발생할 가능성이 높기 때문에 자바 소스를 컴파일하는 과정에서 해당 예외 처리 코드가 있는지 검사. (없을 경우 컴파일 오류 발생)
- 실행 예외(컴파일러 넌 체크 예외) : 실행 시 예측할 수 없이 갑자기 발생하기 때문에 컴파일하는 과정에서 예외 처리 코드가 있는지 검사하지 않음. ▶ 자바 컴파일러가 체크하지 않으므로, 개발자의 경험에 의해 예외 처리 코드를 작성해야 한다.
예외 클래스
자바에서는 예외를 클래스로 관리한다. JVM은 프로그램 실행 도중 예외 발생 시 해당 예외 클래스로 객체를 생성하고, 예외 처리 코드에서 예외 객체를 이용할 수 있도록 해준다.
모든 예외 클래스는 java.lang.Exception 클래스를 상속받는다.
일반 예외와 실행 예외 클래스는 RuntimeException 클래스를 기준으로 구별한다.
- RuntimeException의 하위 클래스: 실행 예외 클래스 ▶ 클래스 상속 관계에서 부모에 RuntimeException이 있다.
- RuntimeException의 하위 클래스 아님: 일반 예외 클래스
[대표적인 실행 예외 클래스 종류]
- NullPointerException: 객체 참조가 없는 상태. null 값을 갖는 참조 변수로 객체 접근 연산자인 도트(.)를 사용했을 때 발생.
- ArrayIndexOutOfBoundsException: 배열에서 인덱스 범위를 초과한 경우. ex) 길이 3인 int[] arr = new int[3] 배열에서 arr[3] 사용 시. ▶ arr[] 범위는 0~2 이므로 ArrayIndexOutOfBoundsException 발생
- NumberFormatException: 문자열로 되어 있는 데이터를 숫자로 변경 시(Integer.parseInt(String s)), 숫자로 변환될 수 없는 문자가 포함되어 있을 경우 발생. ex) String data1 = "100"; ▶ 정수로 변경 가능 / String data2 = "a100"; ▶ 정수로 변경 불가 (NumberFormatException 발생)
- ClassCastException: 상위 클래스-하위 클래스 또는 구현 클래스-인터페이스 등의 관계가 아닌 상태에서는 클래스가 다른 타입으로 변환할 수 없으므로, ClassCastException 발생. ▶ 이러한 예외를 발생시키지 않으려면 타입 변환 전에 instanceof 연산자로 확인 권장.
예외 처리
◆ try-catch-finally 블록
생성자 내부와 메소드 내부에서 작성되어 일반 예외와 실행 예외가 발생할 경우 예외 처리를 할 수 있도록 해준다.
try {
// 예외 발생 코드
} catch(예외 클래스 e) {
// 예외 처리
} finally {
// 항상 실행
}
public class TryCatchFinallyRuntimeExceptionExample {
public static void main(String[] args) {
String data1 = null;
String data2 = null;
try {
data1 = args[0];
data2 = args[1];
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
System.out.println("실행 매개값의 수가 부족합니다.");
return;
}
try {
int value1 = Integer.parseInt(data1);
int value2 = Integer.parseInt(data2);
int result = value1 + value2;
System.out.println(data1 + "+" + data2 + "=" + result);
} catch (NumberFormatException e) {
System.out.println("숫자로 변환할 수 없습니다.");
} finally {
System.out.println("다시 실행하세요.");
}
}
}
※ e.printStackTrace(): 예외 메세지와 스택 트레이스를 출력함으로써, 예외가 발생한 기능을 역으로 추적할 수 있다.
다중 catch
try 블록 내부에 다양한 예외가 발생할 수 있다고 예상될 경우, 발생되는 예외별로 예외 처리르 코드를 다르게 할 때 사용할 수 있다.
try {
// 코드
} catch(예외클래스 e) {
//예외 처리 1
} catch(예외클래스 e} {
// 예외 처리 2
}
catch 블록이 여러 개라 할지라도 단 하나의 catch 블록만 실행되는데, 그 이유는 try 블록에서 동시 다발적으로 예외가 발생하지 않고, 하나의 예외가 발생하면 즉시 실행을 멈추고 해당 catch 블록으로 이동하기 때문이다.
다중 catch 블록 작성 시 주의할 점은 상위 예외 클래스가 하위 예외 클래스보다 아래쪽에 위치해야 한다는 것이다.
앞서 try-catch-finally 예제 코드를 다음과 같이 수정할 수 있다.
public class CatchByExceptionKindExample {
public static void main(String[] args) {
try {
String data1 = args[0];
String data2 = args[1];
int value1 = Integer.parseInt(data1);
int value2 = Integer.parseInt(data2);
int result = value1 + value2;
System.out.println(data1 + "+" + data2 + "=" + result);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("실행 매개값의 수가 부족합니다.");
} catch (NumberFormatException e) {
System.out.println("숫자로 변환할 수 없습니다.");
} finally {
System.out.println("다시 실행하세요.");
}
}
}
예외 떠넘기기
(throws 키워드)
메소드 내부에서 예외 발생 시 경우에 따라서는 메소드를 호출한 곳으로 예외를 떠넘길 수도 있는데, 이때 사용하는 키워드는 throws 이다. throws 키워드는 메소드 선언부 끝에 작성되어 메소드에서 처리하지 않은 예외를 호출한 곳으로 떠넘기는 역할을 한다.
throws는 자바에서 메소드가 특정 예외를 발생시킬 수 있다고 알려주는 방법이다. 이는 마치 "이 메소드를 사용하면 이런 문제가 생길 수 있어요!"라고 경고하는 것이라고 볼 수 있다. 비유를 하자면, 어떤 집에서 손님이 오면, 집주인이 "이 방에 들어가면 고양이가 있을 수 있어요"라고 미리 알려주는 것과 같다. 손님은 고양이를 좋아하지 않다면 방에 들어가기 전에 마음의 준비를 하거나 다른 방으로 가면 된다.
throws 키워드 뒤에는 떠넘길 예외 클래스를 쉼표로 구분해서 나열해주면 된다.
리턴타입 메소드이름(매개변수, ...) throws 예외클래스1, 예외클래스2, ... {
}
또는 아래와 같이 throws Exception 만으로 모든 예외를 간단히 떠넘길 수도 있다.
리턴타입 메소드이름(매개변수, ...) throws Exception {
}
[throws 키워드를 활용한 코드의 예]
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ThrowsExample {
// 파일을 읽는 메소드
public static void readFile(String filePath) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(filePath));
String line = reader.readLine(); // 한 줄 읽기
System.out.println(line);
reader.close();
}
public static void main(String[] args) {
try {
// 파일을 읽는 메소드를 호출
readFile("example.txt");
} catch (IOException e) {
// 만약 예외가 발생하면 여기에서 처리
System.out.println("파일을 열 수 없습니다: " + e.getMessage());
}
}
}
- readFile 메소드:
throws IOException을 통해 이 메소드가 파일을 읽는 중에 문제가 생길 수 있다는 걸 밝힌다. 예를 들어, 파일이 없을 때 발생할 수 있는 예외다.
- main 메소드:
readFile("example.txt")를 호출하는데, 이때 try-catch를 사용하는데, 만약 예외가 발생하면, catch 블록에서 "파일을 열 수 없습니다"라는 메시지를 출력한다.
예제1
Q. Null 참조와 산술 예외 처리
1. 프로그램 실행 시 하나의 args 값을 받아 실행
2. 문자열 배열을 만들고 String 넣기
3. args 인덱스의 문자열 길이를 가져와, 그 길이를 0으로 나누는 연산 수행
4. 배열이 null 이거나 인덱스가 범위를 벗어나거나, 0으로 나누는 예외처리
public class ExceptionTest {
public static void main(String[] args) {
String[] str = { "apple", "banana", "grape" };
try {
int i = Integer.parseInt(args[0]);
String data1 = str[i];
int result = data1.length() / 0;
System.out.println(data1 + "을 0으로 나눈 값:" + result);
} catch (NullPointerException e) { // 배열이 null
System.out.println("객체 참조가 없습니다.");
} catch (ArrayIndexOutOfBoundsException e) { // 인덱스 범위 벗어남
System.out.println("실행 매개값의 수가 부족합니다.");
} catch (ArithmeticException e) { // 정수를 0으로 나눔
System.out.println("0으로 나눌 수 없습니다.");
} finally {
System.out.println("다시 실행해 주세요.");
}
}
}
String args[]
◆ String args[]란?
String args[]는 프로그래밍에서 명령행 인자를 받을 때 사용하는 방법이다.
1. 프로그램 실행:
컴퓨터에서 프로그램을 실행할 때, 사용자가 어떤 정보를 입력할 수 있다. 예를 들어, "안녕하세요!" 또는 숫자 같은 것을 프로그램에 전달할 수 있다.
2. 명령행 인자:
명령행 인자는 프로그램을 실행할 때 입력하는 추가 정보이다.
예를 들어, 프로그램을 실행할 때 java YourProgramName apple banana라고 입력한다고 가정하면 apple과 banana라는 두 개의 정보가 프로그램에 전달된다.
3. String args[]의 역할:
String args[]는 이러한 명령행 인자를 담기 위한 상자. 여기서 String은 글자(문자열)를 의미하고, args는 이 상자의 이름이다.
[]는 이 상자가 여러 개의 정보를 담을 수 있는 배열임을 나타낸다. 즉, 여러 개의 글자를 담을 수 있는 공간이 있다는 뜻이다.
public class MyProgram {
public static void main(String[] args) {
// args 배열의 길이를 출력합니다.
System.out.println("전달된 인자의 개수: " + args.length);
// args 배열의 각 요소를 출력합니다.
for (int i = 0; i < args.length; i++) {
System.out.println("args[" + i + "] = " + args[i]);
}
// 예를 들어, 첫 번째 인자를 숫자로 변환하고 출력합니다.
if (args.length > 0) {
try {
int number = Integer.parseInt(args[0]);
System.out.println("첫 번째 인자를 숫자로 변환: " + number);
} catch (NumberFormatException e) {
System.out.println("첫 번째 인자는 숫자가 아닙니다.");
}
}
}
}
◆ args[]에 값 넣어보기
[Run] - [Run Configurations] 로 들어간 다음,
Argument 탭에서 'Program arguments'에 1이라는 값을 넣게 되면,
args[]에 값이 전달되어 아래와 같은 값이 나오게 된다.
마찬가지로, 예제1에서 Exception 값이 아닌 정상적인 값이 나오게 하려면 우선 코드값을 아래와 같이 바꾸고,
int result = data1.length() / 1;
System.out.println(data1 + "을 1로 나눈 값:" + result);
Run Configuration에서 클래스를 선택하고 Arguments에 정수의 값을 준 뒤 실행하면,
값이 잘 나온다. (finally 내용은 무조건 나온다.)
[참고]
혼자 공부하는 자바
https://kangminhyuk1111.tistory.com/69
다음 내용
'프로그래밍 및 기타 > Java, Spring Boot' 카테고리의 다른 글
[java] java 스레드(thread) - 멀티, 메인, 작업 / 동기화 메소드 (1) | 2025.04.10 |
---|---|
[java] java.lang 패키지 (0) | 2025.04.09 |
[java] 인터페이스 상속, 중첩 클래스, 중첩 인터페이스 (0) | 2025.04.08 |
[java] instanceof, 인터페이스, 구현 클래스 (0) | 2025.04.08 |
[java] 추상 클래스, 추상 메소드 (0) | 2025.04.07 |