목적 : 서비스 중단을 막기 위해서
Throwable
Error(시스템적문제) Exception(코드적 문제)
RuntimeException⭕ RuntimeException❌
참고) Exception을 바로 상속 받은 예외 클래스
예) java.io.IOException / 파일을 읽을때, 쓸때 (FileInputStream, FileOutputStream)
참고) RuntimeException을 상속받았는지 구분하는 법 : 자바문서 보기
참고)
java.exe : 클래스파일 실행
javac.exe : java -> class 컴파일
참고) 컴파일
- 자바에서 컴파일은 소스 코드를 기계어로 변환하는 과정을 의미해요. 이렇게 변환된 기계어 코드는 컴퓨터에서 실행될 수 있어요. 자바의 경우, 소스 코드는 .java 파일에 저장되고, 컴파일된 코드는 .class 파일로 저장돼요. 이 .class 파일은 JVM에서 실행될 때 사용돼요.
cd 파일경로: 파일 이동dir /w: 파일 확인 (.java -> .class 파일로 컴파일 되었는지 확인)javac 파일명: 컴파일
throw 예외객체; = 내부적으로 예외객체 던짐

ㄴ 맨 아랫 줄 : 오류발생 코드라인 위치
try {
// 예외가 발생할 가능성이 있는 코드
} catch (예외 객체 ....) {
// 예외 발생시 처리할 코드
}
예시)

ㄴ 예외발생 시 내부적으로 보이지 않지만 예외객체를 던진다 -> throw new FileNotFoundException
ㄴ 예외가 발생하자마자 던져지기 때문에 아직 예외처리 전인 System.out.println("파일 처리...");는 실행x
ㄴ catch (FileNotFoundException e) {예외 발생시 처리할 코드}
-> FileNotFoundException : 무슨예외인지 명시
-> e : 던져진 예외객체가 담겨져 있는 변수(관례적으로 e를 많이 씀) -> e = new FileNotFoundException
try {
// 예외가 발생할 가능성이 있는 코드
} catch ( 예외 객체1 ....) {
// 예외 발생시 처리할 코드
}
catch ( 예외 객체2 ....) {
// 예외 발생시 처리할 코드
}

ㄴ 예외처리를 했기 때문에 시스템이 다운되지 않고 예외발생이후의 코드도 실행이 된다
= "매우 중요한 코드..." 출력 됨
catch ( 예외 객체1 | 예외 객체2 ) {} try {
// 예외가 발생할 가능성이 있는 코드
} catch ( 예외 객체1 | 예외 객체2 ) {
// 예외 발생시 처리할 코드
}

catch (Exception e) {}catch (Exception e) {} 는 가장 하단에 배치할 것catch (Exception e) {}가 가장 상단에 있으면 하단의 다른 예외처리로 유입이 되지 않기 때문에 실현되지 못함 -> 에러 뜸
try {
} catch (...) {
...
} finally {
// 예외가 발생하든 안하든 항상 실행되는 코드
// return 하더라도 코드가 실행
}
예시) 예외가 발생안해도 실행됨

예시) 예외가 발생해도 실행됨

예시)
import java.io.FileInputStream;
import java.io.IOException;
public class ReadFileExample {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("example.txt");
int data;
while ((data = fis.read()) != -1) {
System.out.print((char) data);
}
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
이 예제에서는 "example.txt" 파일을 FileInputStream을 사용하여 읽고, 읽은 데이터를 콘솔에 출력합니다.
예시1) 왜 예외처리를 IOException으로 했을까?

ㄴ 왜 에러가뜰까?

ㄴ close에 대한 예외처리(IOException) 안해줘서 뜸

ㄴ 근데 보면 FileNotException 의 상위클래스가 IOException 이다!

ㄴ 다형성이용해서 1석2조로 예외처리하자
ㄴ 하지만 처리가 다를 때는 분리해줘야 함
예시 1-1) 예외 발생❌ 시 자원해제

ㄴ 오 근데 b.txt파일은 없으니까 자원해제코드(close)로 유입되기도 전에 예외처리실행되서 catch문으로 갈테니까 a.txt 파일로 바꿔서 로직실현되게 하쟝
ㄴ "자원해제완료!"가 출력되는거 보니 자원해제가 되었겠군 굳굳~
ㄴ여기서 문제 발견!
예시 1-2) 예외 발생⭕ 시 자원해제

ㄴ 이 자원해제 로직은 예외가 없을 때만 실행 될 수 있군!
ㄴ 자원해제는 예외가 있든 없든 실행되야 하는뎅

ㄴ 이때는 try ~ catch 밖으로 빼줘야 함
ㄴ FileInputStream fis = null; 을 try ~ catch 밖으로 빼주고 try ~ catch 밖 안의 fis = new FileInputStream("b.txt"); 에 대입해주는 식으로 하면 예외가 발생해도 자원해제코드(close) 실행됨❓

ㄴ 값이 있거나 혹은 객체가 안만들어 질 때도 있음
ㄴ 그럴때도 자원해제를 해야하니 if문 작성

ㄴ 처리로직 썻더니 에러 뜸 -> 예외처리안해서 에러 뜸

ㄴ try ~ catch로 감싸줌
ㄴ 이제 예외 발생해도 자원해제 로직 실행 됨

ㄴ 근데 try구문에도 close(예외발생❌시 자원해제코드)가 있고 catch구문에도 close(예외발생⭕시 자원해제코드)가 있고 중복되넹?
ㄴ finally 쓰면 되지 않낭?
-> finally : 예외가 발생하든 안하든 항상 실행되는 코드
예시1-3) finally
package exam02;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Ex04 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("b.txt");
System.out.println("파일 작업...");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
}
}
}
}
}
ㄴ finally를 씀으로서 예외가 발생하든 안하든 자원해제⭕
ㄴ 코드가 넘 길어...
-> try-with-resources문으로 코드 줄일 수 있음
JDK7에서 추가
AutoCloseable 인터페이스의 구현 클래스이면 close() 메서드를 자동 호출하여 자동으로 자원해제
-> try-catch-finally문을 이용한 자원해제 시 코드가 긴 것을 보완
자원 자동해제의 기준 : AutoCloseable 인터페이스의 구현 클래스
-> close() 메서드를 자동 호출
-> AutoCloseable 인터페이스의 구현 객체가 아니면 자원해제 안해 줌
자원해제가 필요한 거의 모든클래스는 AutoCloseable 인터페이스의 구현체
try ( 해제할 자원 객체1;
해제할 자원 객체2 ...) {
// 예외가 발생할 가능성이 있는 코드
} catch(예외 객체 ...) {
}
참고)
instanceof
예시) try-with-resources문

ㄴ 자동으로 close호출됨

ㄴ 클릭

ㄴ 자원해제가 필요한 모든 클래스에 AutoCloseable 인터페이스가 추가되어 있음
-> try-with-resources문을 쓰기 위해서

ㄴ close() : AutoCloseable 인터페이스의 추상메서드
ㄴ 이걸 정의하면 try-with-resources문이 자동으로 정의한 close()메서드를 호출해줌

ㄴ Resources클래스 : 자원해제가 필요한 클래스
@Override
public void close() throws Exception {
System.out.println("자원해제!!");
}
ㄴ AutoCloseable 인터페이스의 추상메서드 정의함

ㄴ res가 AutoClosable 인터페이스 구현 객체인지 체크 -> close() 메서드 자동 호출
ㄴ 투입되는 객체가 다양할텐데 res가 AutoClosable 인터페이스 구현 객체인지 어떻게 체크하지?

// 보이지 않지만 이러한 처리로직에 의해서 close()가 자동호출된다
AutoCloseable auto = res; // 내부적인 처리로직 -> 다형성이용해서 AutoClosable 인터페이스의 구현체인지 쳌 + 형변환
auto.close(); // 내부적인 처리로직 -> close()호출
ㄴ 투입되는 객체가 AutoClosable 인터페이스의 구현체이면 형변환이 되겠고 그러면 close가 호출 될 것이다
-> try-with-resources문을 쓸 때 내부적으로 이러한 처리로직이 담겨 있다ㅏ
-> 다형성


ㄴ "자원해제" 멘트가 출력된거보니 진짜 close() 메서드가 자동 호출되었넹
메서드를 호출 하는쪽에서 예외 처리를 하도록 전가
RuntimeException을 상속받은 경우
Exception을 상속 받은 경우(RuntimeException이 없는 경우)
전가시키는 예외에 대해서 명시(throws)
-> 메서드 매개변수 뒤쪽에 throws 전가할 예외 작성
-> 메서드 매개변수 + throws 전가할 예외
예시) Exception을 상속 받은 경우

ㄴ 전가시키는 예외에 대해서 명시(throws)

ㄴ 메서드를 호출 하는쪽에서 예외 처리

ㄴ 예외처리로직이 동일하니 다형성을 이용하여 처리해야할 예외 2개를 Exception e 1개로 퉁치자
예시) RuntimeException을 상속 받은 경우
Exception을 상속 받은 경우 형식을 엄격히 유지해야 하기 때문에 유연성이 떨어져 잘 안씀
↔ RuntimeException을 상속 받은 경우 형식이 유연하기 때문에 많이 사용

ㄴ UserPwException이 RuntimeException을 상속받음

ㄴ UserIdException이 RuntimeException을 상속받음

ㄴ Exception을 상속 받은 경우와 달리 RuntimeException을 상속받은 경우 전가시키는 예외에 대해서 명시(throws)하지 않아도 됨
-> 형식의 유연성

ㄴ Exception을 상속 받은 경우와 달리 RuntimeException을 상속받은 경우 try ~ catch 안써도 오류 발생x -> 형식의 유연성
ㄴ 근데 이건 위험한 방법 , 만약 예외가 발생하면 서비스 다운 -> 조심히 써야한다
super(...))예시)
유저 아이디 : user01, 비번 : 123456이 아니면 검증이 실패했다는 예외를 발생시켜 사용자에게 알려주기 = 필요한 경우에 정의하는 사용자 정의 예외

ㄴ 아이디 예외클래스 : 사용자 정의 예외
ㄴ UserIdException이 Exception의 바로 하위클래스라소 바로 상속시행
-> 만약 중간에 다른 클래스ex) RuntimeException...가 껴있으면 상속에 상속을 해줘야 함

ㄴ 비번 예외클래스 : 사용자 정의 예외
ㄴ 예외클래스 상속 + 생성자 정의 + 상위클래스 생성자에게 처리 위임(super(...))
ㄴ 참고) 생성자 매개변수 여러개 설정 가능

ㄴ 예외객체 생성 후 던지기
ㄴ 빨간색으로 오류 발생 왜?
-> UserIdException, UserPwException은 Exception의 바로 하위클래스이니 RuntimException을 중간에 상속받지 않았기 때문에 엄격한 예외임
-> 예외가 발생하든 안하든 예외처리 해줘야 함
-> try ~ catch 정의하자

ㄴ 예외처리함
ㄴ e.getMessage() : "아이디가 일치하지 않습니다", "비밀번호가 일치하지 않습니다."

ㄴ 예외가 발생하지 않을 때 출력할 멘트 설정함

ㄴ 음 사용자 정의 예외처리가 잘 시행 됬군