예외처리
프로그램 오류
- 컴파일 에러 : 컴파일 시에 발생하는 에러
- 런타임 에러 : 실행 시에 발생하는 에러
- 논리적 에러 : 실행은 되지만 의도와 다르게 동작하는 것
예외 클래스의 계층 구조
- Exception 클래스와 그 자손들
- Exception 클래스 아래에 RuntimeException 클래스와 그 자손들
- runtimeException은 unchecked Excption을 상속한 클래스
- 그 외는 checked Exception을 상속한 클래스
예외 처리
- try~catch문
- 예외를 메서드에 선언
- throws 뒤에 예외를 적어줌
- 예외를 선언함으로써 메서드를 사용하려는 사람이 메서드의 선언부를 보았을 때 어떤 예외들이 처리되어야 하는지 쉽게 알 수 있음
- 자신을 호출한 메서드에게 예외를 전달하여 예외처리를 떠맡김
- finally 블럭은 예외 발생과 상관없이 실행되어야 할 코드를 포함시킬 목적으로 사용된다
- try~catch문의 끝에 선택적으로 사용
- try~catch~resources문
- I/O 관련된 클래스를 사용할 때 유용
- 입출력에 사용되는 클래스 중에서 사용한 후 꼭 닫아줘야 하는 것들을 쉽게 닫을 수 있다
- 자동으로 객체의 close()가 호출될 수 있으려면 클래스가 AutoCloseable이라는 인터페이스를 구현한 것이어야 한다
// try~catch
try {
fis = new FileInputStream("score.dat");
dis = new DataInputStream(fis);
} catch (IOException ie) {
ie.printStackTrace();
} fianlly {
try {
if (dis != null) {
dis.close();
}
} catch (IOException ie) {
ie.printStackTrace();
}
}
// try~catch~resources
// 괄호 안에 두 문장 이상을 넣을 경우 ';'로 구분한다
try (fis = new FileInputStream("score.dat");
dis = new DataInputStream(fis)) {
while(true) {
score = dis.readInt();
sum += score;
}
} catch (IOException ie) {
System.out.println("점수의 총합은 " + sum + "입니다.");
} catch (IOException ie) {
ie.printStackTrace();
}
사용자정의 예외
- 보통 Exception클래스 또는 RuntimeException 클래스를 상속받아 클래스를 만든다
예외 되던지기
- 예외가 발생한 메서드와 호출한 메서드 양쪽에서 처리하도록 할 수 있다
- 예외를 처리한 후에 인위적으로 다시 발생시키는 방법을 사용한다
연결된 예외
- 한 예외가 다른 예외를 발생시키는 구조인 경우
- 예외 발생 시 그 예외를 다른 예외의 원인 예외로 등록한 뒤에 throw로 던진다
- 여러 예외를 하나의 큰 분류의 예외로 묶어서 다루기 위해 사용된다
- checked 에외를 unchecked 예외로 바꿀 수 있도록 하기 위해서
- checked 예외를 unchecked 예외로 변경했을 경우 의미없는 예외 처리를 하지 않아도 된다
optional API
- Java8부터 Optional을 제공하여 null로 인한 예외가 발생하지 않도록 도와주고 Optional 클래스의 메소드를 통해 null을 컨트롤 할 수 있다
java.lang 패키지와 유용한 클래스
얕은 복사와 깊은 복사
- clone()은 객체에 저장된 값을 그대로 복제할 뿐, 객체가 참조하고 있는 객체까지 복제하지 않는다
- 원본과 복제본이 같은 객체를 공유하므로 완전한 복제라고 보기엔 어렵기 때문에 이러한 복제를 얕은 복사라고 한다
- 얕은 복사에서는 원본을 변경하면 복사본도 영향을 받는다
- 원본이 참조하고 있는 객체까지 복제하는 것은 깊은 복사라고 한다
- 깊은 복사에서는 원본과 복사본이 서로 다른 객체를 참조하기 때문에 원본의 변경이 복사본에 영향을 미치지 않는다
stringBuffer 클래스와 stringBuilder 클래스
- String 클래스는 인스턴스를 생성할 때 지정된 문자열을 변경할 수 없지만 StringBuffer 클래스는 변경이 가능하다
- 내부적으로 문자열 편집을 위한 버퍼를 가지고 있으며, StringBuffer 인스턴스를 생성할 때 그 크기를 지정할 수 있다
wrapper 클래스
- 기본형 변수를 객체로 다뤄야 할 때 사용되는 것이 래퍼 클래스이다
- 기본형 값을 래퍼 클래스의 객체로 자동 변환해주는 것이 오토박싱
- 반대로 변환하는 것이 언박싱