Java 예외클래스의 최상위 →
Object
모든 예외클래스 →Throwable
클래스 상속받음
문제 발생 시, 복구 불가능 🚨
어플리케이션 자동종료 (Error의 경우, 복구시도 자체를 ⛔️)
모든 예외클래스들이 상속하는 클래스
RuntimeExceptions
→ UnCheckedException
OtherExceptions
→ CheckedException
Exception | 의미 |
---|---|
IllegalArgumentException | 적절하지 못한 인자를 메서드에 넘겨주었을 때 |
ArithmeticException | 산수문제 (0으로 나눌 때) |
NullPointerException | Null 오브젝트로 접근했을 때 |
e.getClass() | 예외가 발생한 상위클래스 name 가져옴 |
e.getName() | e(예외클래스 객체)의 상위클래스(예외클래스) name 가져옴 |
e.getMessage() | 예외발생 시, 예외메시지 |
printStackTrace() | 예외발생 당시의 호출스택에 있었던 메서드정보와 예외메시지 화면에 출력 |
📌 재시도
: 일정시간 대기 후, 로직을 다시 실행하는 방법
최대로 시도할 횟수를 정함 → 최대 횟수를 채울 때까지 다시 반복
try-catch
에서 예외처리를 하는것이 아님 ⛔️
try-catch
→ 최대 횟수 넘기면 ➡️ CheckedException
예외발생 ✅
@Test
public void 예외_재시도() {
final int MAX_COUNT = 5;
int tryCount = MAX_COUNT;
while(tryCount < MAX_COUNT) {
try {
// 로직 실행
return; // 성공적인 종료
} catch(Exception e) {
// 실패 -> 일정시간 대기
} finally {
// 자원해제
}
}
throw new RunTimeException(); // 예외발생
}
📌 책임회피
: 발생한 Exception 내가 처리 ❌ → 나를 호출한 쪽으로 책임회피
나를 호출 한 쪽 : 내 메서드를 실행시킨 (상위)메서드
명시적으로 메서드 명 옆에 throws
붙임
@Test
public void 책임_회피() throws FileNotFoundException {
BufferedReader br = new BufferedReader(new FileReader("c:/out.txt"));
// 파일 입출력 로직
}
📌 예외전환
: 예외 발생 시, 다른 예외를 던짐
책임회피
: 내 예외를 그대로 다른쪽으로 던짐
예외전환
: 내가 의도한 다른 예외를 다시 발생시킴 → 의도된 예외전환 ⭐️
@Test
public void 예외_전환() {
if(/*로그인 시도 5회 실패*/) {
throw new LoingFailedFiveTimeException();
}
// 로그인 로직
}
Unchecked Exception (Runtime) | Checked Exception (Other) | |
---|---|---|
클래스 | Runtime Exception 클래스 + 자손클래스 | Exception 클래스 자손 중, Runtime Exception 제외한 모든클래스 |
확인시점 | 실행단계 | 컴파일단계 |
강제처리여부 | 강제처리 ❌ | 반드시 강제처리(예외처리) ✅ |
예외발생 시, 트랜잭션처리 | rollback ✅ | rollback ❌ |
대표예외 | NullPointException IllegalArgumentException | IOException SQLException |
가장 큰 차이점 → 강제처리 해야하는가 ? / 아닌가 ?
📍 Checked Exception : throws 던지거나, try-catch 필수
📍 Unchecked Exception : 개발자 부주의코딩에 의해 발생하는 예외
@Test
public void IOException() {
ObjectMapper objectMapper = new ObjectMapper();
MemberVo member = new MemberVo();
String memberJson = objectMapper.writeValueAsString(member);
}
ObjectMapper : 객체와 Json문자열을 상호변환해주는 기능의 객체
JsonProcessingException
처리하라는 경고 🚨
@Test
public void Throws던지기() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
MemberVo member = new MemberVo();
String memberJson = objectMapper.writeValueAsString(member);
}
Throws던지기() 메서드
→ 호출한 쪽으로 예외처리를 위임함
장점 : 해당메서드에 명시적처리 ❌, 코드에 예외처리가 없어 가독성이 좋음
단점 : 연속적으로 메서드호출 → 책임회피가 늘어날수록 → 상위에 있는 메서드의 throws 코드가 지저분해지고 예외의 위치를 찾는게 어려워짐
@Test
public void Try-Catch감싸기() {
ObjectMapper objectMapper = new ObjectMapper();
MemberVo member = new MemberVo();
try {
String memberJson = objectMapper.writeValueAsString(member);
} catch (JsonProcessingException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
예외가 발생 → 해당부분을 try-catch로 감쌈 → 해당 메서드 내에서 예외를 처리함
장점 : 예외처리를 책임지고 처리 → 예외 전파 ❌
단점 : 모든 예외마다 try-catch 사용 → 코드가 많이 늘어나 가독성이 떨어짐
try {
// 예외가 발생할 가능성이 있는 코드
} catch (Exception1 e1) {
// Exception1이 발생했을 때, 이를 처리하기 위한 코드
} catch (Exception2 e2) {
// Exception2가 발생했을 때, 이를 처리하기 위한 코드
}
📌 Try 블럭 → 여러개의 catch 블럭이 올 수 있음
📌 발생한 예외의 종류와 일치하는 단 한개의 catch 블록만 수행됨
Exception
: 발생한 예외에 대한 예외클래스e
: 예외클래스의 객체를 가리키는 참조변수
public class ExceptionDemo {
public static void main(String[] args) {
try {
// 1을 0으로 나눴으므로 예외가 발생한다.
System.out.println(1 / 0);
} catch (IllegalArgumentException e) {
System.out.println(e.getClass().getName());
System.out.println(e.getMessage());
} catch (ArithmeticException e) { // catch문 실행
System.out.println(e.getClass().getName());
System.out.println(e.getMessage());
} catch (NullPointerException e) {
System.out.println(e.getClass().getName());
System.out.println(e.getMessage());
}
}
}
→ ArithmeticException
catch 실행됨
public class ExceptionDemo {
public static void main(String[] args) {
try {
System.out.println(1 / 0); // 예외발생
} catch (IllegalArgumentException | ArithmeticException e) {
// 예외 클래스 2개를 or(|)로 연결, 인스턴스는 1개
System.out.println(e.getMessage());
}
}
}
→ JDK 1.7부터 catch block 하나로 합칠 수 있음
public class ExceptionDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("아이디를 입력하시오");
String username = scanner.nextLine();
try {
if (username.equals("바보")) {
throw new IllegalArgumentException("부적절한 이름입니다.");
}
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}
📌 유효성 검사 시,
throw
→ 고의로 예외를 발생시킴
new
: 예외클래스 생성throw
: 해당 예외 발생
void method() throws Exception1, Exception2 ••• {
// 메서드내용
}
📌
throws
→ 메서드에 예외를 선언함
- 메서드선언부에 예외선언 → 어떤 예외를 처리해야하는지 알 수 있어 가독성 ✅
- 해당메서드에서 예외처리 ❌ → 해당메서드를 사용하는 쪽이 예외를 처리하도록 책임전가
public class ExceptionDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
try {
System.out.println("파일 이름을 입력하시오");
String fileName = scanner.nextLine();
File f = createFile(fileName);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
static File createFile(String fileName) throws Exception {
if (fileName == null || fileName.equls("")) {
throw new Exception("파일이름이 유효하지 않습니다");
}
File f = new File(fileName);
f.createNewFile();
return f;
}
}