try-catch
- 예외를 처리할 때 사용하는 코드
- 실행할 코드는 try 블록에 두고 예외를 처리할 코드는 catch 블록에 두는 방식
- try 블록의 코드를 실행하다가 예외가 발생되면 발생된 예외는 자동으로 catch 블록으로 전달됨
- 모든 예외는 자바 클래스로 만들어져 있음
- 형식:
try {
실행코드
} catch(예외타입선언 e) {
예외처리코드
}
try-catch 예시
public static void m1() { try { String[] hobbies = new String[3]; hobbies[1] = "swimming"; hobbies[2] = "running"; for(String hobby : hobbies) { System.out.println(hobby.substring(0, 2)); // null 값 때문에 오류 발생 } } catch(Exception e) { // RuntimeException, NullPointerException 가능 System.out.println("NullPointerException 발생"); } }
출력:
NullPointerException 발생
연습문제1
public static void m2() { try { String input = "20,21,22,,23,24,25"; String[] inputs = input.split(","); int[] ages = new int[inputs.length]; // 길이가 6인 배열 만들기 for(int i = 0; i < inputs.length; i++) { ages[i] = Integer.parseInt(inputs[i]); System.out.println("변환 값 : " + ages[i]); } } catch(NumberFormatException e) { // RuntimeException, Exception 가능 System.out.println("NumberFormatException 발생"); } catch(Exception e) { System.out.println("Exception 발생"); } }
- Exception은 NumberFormatException을 포함하기 때문에 catch(Exception e)를 먼저 작성하면 오류가 난다.
출력:
변환 값 : 20
변환 값 : 21
변환 값 : 22
NumberFormatException 발생
연습문제2
public static void m3() { try { Scanner sc = new Scanner(System.in); System.out.println("정수1 >>> "); int a = sc.nextInt(); System.out.println("정수2 >>> "); int b = sc.nextInt(); System.out.println(a + "+" + b + "=" + (a+b)); System.out.println(a + "-" + b + "=" + (a-b)); System.out.println(a + "*" + b + "=" + (a*b)); System.out.println(a + "/" + b + "=" + (a/b)); System.out.println(a + "%" + b + "=" + (a%b)); sc.close(); } catch(ArithmeticException e) { System.out.println("ArithmeticException 발생"); } catch(InputMismatchException e) { System.out.println("InputMismatchException 발생"); } }
정수2에 0 입력시 출력:
ArithmeticException 발생
소수점 입력시 출력:
InputMismatchException 발생
Checked Exception
public static void m4() { try { File file = new File("C:\\sample.txt"); FileReader fr = new FileReader(file); // try-catch문이 없으면 실행이 불가능한 Checked Exception } catch (Exception e) { } }
finally 블록
- try-catch문 마지막에 추가하는 블록
- 언제나 마지막에 실행되는 블록
- 생략 가능
public static void main(String[] args) { Scanner sc = new Scanner(System.in); try { System.out.println("나이 입력 >>> "); String strAge = sc.nextLine(); int age = Integer.parseInt(strAge); System.out.println(age >= 20 ? "성인" : "미성년자"); } catch (Exception e) { System.out.println("예외 발생"); } finally { sc.close(); System.out.println("finally 블록 실행"); } }
throw
- 예외 객체를 만들어서 직접 throw할 수 있다.
- 자바는 예외로 인식하지 않지만 실제로는 예외인 경우에 주로 사용된다.
public static void main(String[] args) { Scanner sc = new Scanner(System.in); try { System.out.println("나이 입력 >>> "); String strAge = sc.nextLine(); int age = Integer.parseInt(strAge); if(age < 0 || age > 100) { throw new RuntimeException("나이는 0 이상 100 이하만 가능합니다."); } System.out.println(age >= 20 ? "성인" : "미성년자"); } catch (Exception e) { System.out.println("예외 발생"); } finally { sc.close(); // 실제로 finally는 자원을 반납할 때 주로 사용됨 System.out.println("finally 블록 실행"); } }
- throw는 예외 발생해도 출력되지 않고, catch문의 e가 받는다.
출력:
나이 입력 >>>
10000000
예외 발생
finally 블록 실행
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
try {
System.out.println("나이 입력 >>> ");
String strAge = sc.nextLine();
int age = Integer.parseInt(strAge);
if(age < 0 || age > 100) {
throw new RuntimeException("나이는 0 이상 100 이하만 가능합니다.");
}
System.out.println(age >= 20 ? "성인" : "미성년자");
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
sc.close(); // 실제로 finally는 자원을 반납할 때 주로 사용됨
System.out.println("finally 블록 실행");
}
}
출력:
나이 입력 >>>
1000000
나이는 0 이상 100 이하만 가능합니다.
finally 블록 실행
throws
- 메소드 외부로 예외를 던질 때 throws문을 이용해 던지는 예외를 명시함.
- 2개 이상의 예외를 명시할 수 있기 때문에 throw가 아닌 throws라고 함.
public class ParkingLot { private Car[] cars; private int idx; private Scanner sc; public ParkingLot() { cars = new Car[10]; sc = new Scanner(System.in); } public void addCar() throws RuntimeException { if(idx == 0) { throw new RuntimeException("FULL"); } } public void deleteCar() throws RuntimeException { if(idx == 0) { throw new RuntimeException("EMPTY"); } } public void findCar() throws RuntimeException { if(idx == 0) { throw new RuntimeException("EMPTY"); } } public void printAllCars() throws RuntimeException { if(idx == 0) { throw new RuntimeException("EMPTY"); } } public void manage() { while(true) { try { System.out.print("1. 추가 2. 제거 3. 조회 4. 전체목록 0. 종료 >>> "); int choice = sc.nextInt(); switch(choice) { case 1 : addCar(); break; case 2 : deleteCar(); break; case 3 : findCar(); break; case 4 : printAllCars(); break; case 0 : return; default : throw new RuntimeException("Bad Request"); } } catch(InputMismatchException e) { sc.next(); System.out.println("처리 명령은 정수(1~4,0)입니다."); } catch(RuntimeException e) { System.out.println(e.getMessage()); } } } public static void main(String[] args) { new ParkingLot().manage(); } }
사용자 정의 예외 클래스
- Exception 클래스를 상속 받는다.
- Serializable 인터페이스 : 이 인터페이스를 구현하면 직렬화가 가능. serialVersionUID 값을 가져야 함(추천)
↑- Throwable 클래스 : serialVersionUID 값이 필요함
↑- Exception 클래스 : serialVersionUID 값이 필요함
↑- MyException 클래스 : serialVersionUID 값이 필요함
MyException 클래스
public class MyException extends Exception { private static final long serialVersionUID = -2605896340659853763L; private int errorCode; public MyException(String message, int errorCode) { super(message); this.errorCode = errorCode; } public int getErrorCode() { return errorCode; } public void setErrorCode(int errorCode) { this.errorCode = errorCode; } }
> ## ParkingLot 클래스 ```java public class ParkingLot { private Car[] cars; private int idx; private Scanner sc; public ParkingLot() { cars = new Car[10]; sc = new Scanner(System.in); } public void addCar() throws MyException { if(idx == cars.length) { throw new MyException("Full", 1000); // 에러코드 1000 } } public void deleteCar() throws MyException { if(idx == 0) { throw new MyException("EMPTY", 2000); // 에러코드 2000 } } public void manage() { while(true) { try { System.out.println("1.추가 2.삭제 3.종료 >>> "); int choice = sc.nextInt(); switch(choice) { case 1: addCar(); break; case 2: deleteCar(); break; case 0: return; default: throw new RuntimeException("Bad Request"); } } catch(MyException e) { System.out.println(e.getMessage() + "[" + e.getErrorCode() + "]"); } catch(InputMismatchException e) { sc.next(); System.out.println("처리 명령은 정수만 가능"); } catch(RuntimeException e) { System.out.println(e.getMessage()); } } } public static void main(String[] args) { new ParkingLot().manage(); } }