👉 예외 처리가 필요한 이유
but, 실행 오류가 발생한 경우 오류의 과정을 재현하는 것은 현실적으로 힘들다. . .
👉 로그를 효율적으로 남기는 것을 고민!
모든 예외 클래스의 최상위 클래스는 Exception 클래스
예외 | 예외 발생 상황 |
---|---|
ClassNotFoundException | 존재하지 않는 클래스를 사용하려고 했을 때 |
IOException | 입/출력 작업 과정에서 문제가 발생했을 때 |
SQLException | 데이터베이스 연동 과정에서 문제가 발생했을 때 |
NumberFormatException | 숫자 형식이 아닌 데이터를 숫자로 변경하려고 했을 때 |
ClassCastException | 클래스에 대한 불가능한 타입변환을 시도하려고 했을 때 |
ArrayIndexOutOfBoundsException | 존재하지 않는 배열 공간을 사용하려고 했을 때 |
NullPointerException | 주소가 할당되지 않은 참조변수를 사용하려고 했을 때 |
ArithmeticException | 숫자를 0으로 나누는 등의 불가능한 산술연산을 수행할 때 |
Arithmetic Exception
→ 정수를 0 으로 나눈 경우 발생
NullPointerException
→ 초기화 되지 않은 Object를 사용하는 경우
ArrayIndexOutOfBoundsException
→ 배열의 크기를 넘어선 위치를 참조하려는 경우
FileNotFoundException
→ 참조하는 파일이 지정된 위치에 존재하지 않는 경우
ClassNotFoundException
→ Class.forName(“sis.studentinfo.Student”); // 클래스가 로드되지 않은 경우
InterruptedException
→ Thread.sleep(), join(), Object의 wait()로
non-runnable
상태인 thread를 Runnable
하게 만들 수 있도록 사용할 수 있음
try-catch
문try
블록에는 예외가 발생할 가능성이 있는 코드를 작성
try
블록 안에서 예외가 발생하는 경우 catch
블록이 수행
다중 catch
문도 사용 가능
trace 기능 : 아래 콘솔창에 찍히는 것
int[] arr = {1,2,3,4,5};
try{
for(int i=0; i<=5; i++){
System.out.println(arr[i]);
}
}catch(ArrayIndexOutOfBoundsException e){
System.out.println(e);
}
System.out.println("비정상 종료되지 않았습니다.");
출력결과
비정상 종료되지 않았습니다.
try-catch-finally
문finally
블럭에서 파일를 닫거나 네트웍을 닫는 등의 리소스 해제 구현을 함try{}
블럭이 수행되는 경우에도finally{}
블럭은 항상 수행 됨catch
블럭에 return
이 있어도 수행됨 FileInputStream fis = null;
try {
fis = new FileInputStream("a.txt");
System.out.println("read");
} catch (Exception e) {
System.out.println(e);
// return; // 예외발생해도 finally는 동작함
} finally { // 항상 동작
if(fis != null) {
try {
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("finally");
}
System.out.println("end");
출력결과
만약 return;
이 있다면? end 제외 finally 만 출력
try-with-resources
문close()
하지 않아도 자동으로 해제 되도록 함try()
내부에서 선언해야만 함close()
를 명시적으로 호출하지 않아도 try{}
블록에서 열린 리소스는 ?AutoCloseable
인터페이스를 구현 해야 함FileInputStream
의 경우에는 AutoCloseable
을 구현하고 있음try()
외부에서 선언하고, 변수만을 try(obj)
와 같이 사용 try(FileInputStream fis = new FileInputStream("a.txt")) {
System.out.println("read");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 자동으로 close() 메서드 호출
System.out.println("end");
throw new Exception();
예외 강제 생성(아래에서 자세하게 설명) AutoCloseableObj obj = new AutoCloseableObj();
try(obj) {
// 아무 코드 없어도 try블록 끝나면? 자동으로 AutoCloseable
// => AutoCloseableObj.java의 closing이 잘 출력됨
throw new Exception(); // 예외 강제 생성후, catch문으로 이동함
} catch (Exception e) {
System.out.println("exception");
}
System.out.println("end");
throws
예외 일괄 처리
,
예외 여러개 처리 가능// loadClass() 메서드를 쓰는 쪽(main)에서 핸들링하도록 throws
public Class loadClass(String fileName, String className) throws FileNotFoundException, ClassNotFoundException {
FileInputStream fis = new FileInputStream(fileName);
Class c = Class.forName(className);
return c;
}
public static void main(String[] args) {
ThrowsException test = new ThrowsException();
try {
test.loadClass("a.txt", "abc"); // "java.lang.String" 하면 loadClass() 메서드 잘 수행되었으므로 end만 출력
} catch (FileNotFoundException e) { // 파일 없으면
System.out.println(e);
} catch (ClassNotFoundException e) { // 파일 있지만 클래스 없으면
System.out.println(e);
}
System.out.println("end");
}
throw
예약어-
) 개념이 없음throw
를 사용하여 프로그램이 더 이상 진행되지 않도록 함throw new IllegalArgumentException();
사용자 정의 예외 클래스가
Exception
클래스를 직접 상속 or RuntimeException
상속할지 결정
보통 RuntimeException
을 상속하여 컴파일을 통과하는 예외로 만듦
public void setPassword(String password) throws PassWordException{
if(password == null) {
throw new PassWordException("비밀번호는 null일 수 없습니다");
}
else if(password.length() < 5) {
throw new PassWordException("비밀번호는 5자 이상이어야 합니다");
}
else if(password.matches("[a-zA-Z]+")) { // 정규표현식
throw new PassWordException("비밀번호는 숫자나 특수문자를 포함해야 합니다");
}
this.password = password;
}
main
PasswordTest test = new PasswordTest();
String password = null;
try {
test.setPassword(password);
System.out.println("오류없음1");
} catch (PassWordException e) {
System.out.println(e.getMessage());
}
password = "abc";
try {
test.setPassword(password);
System.out.println("오류없음2");
} catch (PassWordException e) {
System.out.println(e.getMessage());
}
password = "abcde";
try {
test.setPassword(password);
System.out.println("오류없음3"); // 실행
} catch (PassWordException e) {
System.out.println(e.getMessage());
}
// set 실행
password = "abcde1#";
try {
test.setPassword(password);
System.out.println("오류없음4");
} catch (PassWordException e) {
System.out.println(e.getMessage());
}