본문 바로가기

JAVA/Effective Java

item 87) 커스텀 직렬화 형태를 고려해보라 기본 직렬화 : Serializable 인터페이스 구현 커스럼 직렬화 : 커스텀 writeObject, readObject 작성 괜찮다고 판단될때만 기본 직렬화 형태를 사용하라. - 객체의 물리적 표현과 논리적 내용이 같다면 사용해도 무방하다. public class Name implements Serializable { /** * 성. null이 아니어야함 * @serial */ private final String lastName; /** * 이름. null이 아니어야 함. * @serial */ private final String firstName; /** * 중간이름. 중간이름이 없다면 null. * @serial */ private final String middleName; } 사람의 이름은.. 더보기
item 88) readObject는 방어적으로 작성하라 - readObject도 바이트 스트림을 인수로 받는 일종의 public 생성자 - 다른 생성자와 똑같은 수준으로 주의를 기울여야한다. - 인수가 유효한지 검사해야하고 필요하다면 매개변수를 방어적으로 복사해야한다.(불변성 유지) public final class Period implements Serializable { //기본 직렬화 사용 private Date start; private Date end; public Period(Date start, Date end) { this.start = new Date(start.getTime()); this.end = new Date(end.getTime()); if (this.start.compareTo(this.end) > 0) { throw new Il.. 더보기
item 81) wait와 notify보다는 동시성 유틸리티를 애용하라 wait와 notify를 꼭 사용해야 할 이유가 줄었다. - 자바 5에서 도입된 고수준의 동시성 유틸리티가 wait, notify를 직접 사용해서 하던 일들을 대신 처리해줌(java.util.concurrent) - 실행자 프레임워크 (Executors) - 동시성 컬렉션(concurent collection) - List, Queue, Map 같은 표준 컬렉션 인터페이스에 동시성을 부여한 것 - 각자 내부에서 동기화를 수행하므로 동시성을 무력화 하는 것이 불가능하고 외부에서 Lock를 사용하면 오히려 속도가 느려진다. - 여러 메서드를 원자적으로 묶어서 호출하는 것 또한 불가능하다. - 여러 기본 동작을 하나의 원자적 동작으로 묶는 상태 의존적 수정 메소드들이 추가되었다. (Java 8 default .. 더보기
item 73) 추상화 수준에 맞는 예외를 던지라 상위계층에서는 저 수준 예외를 잡아 자신의 추상화 수준에 맞는 예외로 던져야 한다.(예외 번역) - 메서드가 저수준 예외를 처리 하지않고 바깥으로 전파 해버릴 경우 수행하려는 일과 전혀 상관없는 예외가 발생할수 있음 - 예외로 내부 구현방식을 드러내고, 윗레벨 API를 오염시켜버림 - 예외 전파보다는 예외 번역을 사용하라 try { // 저수준 추상화를 이용 } catch (LowerLevelException e) { throw new HigherLevelException(); } //AbstractSequentialList public E get(int index) { ListIterator i = listIterator(index); try { return i.next(); } catch (NoSuc.. 더보기
item74) 메서드가 던지는 모든 예외를 문서화해라 메서드가 던지는 예외를 문서화하는데 충분한 시간을 쏟아야한다. 검사 예외는 항상 따로따로 선언하고, 각 예외가 발생하는 상황을 JavaDoc의 @throws 태그를 활용하여 정확히 문서화하라. - Exception이나 Throwable 같은 공통 상위 클래스가 아니라 구체적인 예외 클래스로 남겨놓을것 - 각 예외에 대처할 힌트도 못 줄뿐더러 다른 예외들까지 포함시켜버려 API 사용성을 떨어뜨린다. - 단, main 함수는 JVM만이 호출하므로 Exception을 던져도 괜찮다. - public 메서드에 대해서는 비검사 예외도 문서화 하는 것이 좋다. 자신이 일어난 예외상황을 무엇인지 설명해주면 프로그래머가 해당 오류가 나지 않도록 코드를 고칠수 있다. 비검사 예외와 검사예외를 구분하는 것이 좋다. - 메.. 더보기
item 72) 표준 예외를 사용하라. 자바 라이브러리는 대부분 API에서 사용하기 좋은 예외를 제공한다. - 코드 재사용 측면에서 좋다. 예외도 마찬가지. - 내 API를 다른 사랑미 사용하기 더 쉽다.(이미 익숙한 규약을 따르기 때문) - 예외 클래스가 적을 수록 메모리 사용량도 줄어든다. 주로 사용하는 예외들 - 가능하다면 더 특수한 예외를 따로 구분해서 사용하라 IllegalArgumentException - 인수로 부적절한 값을 넘길때 발생하는 예외 ex ) 반복횟수에 음수를 건넨 경우 IllegalStateException - 대상 객체의 상태가 메서드를 수행하는데 적합하지 않은 경우 ex) 초기화 되지 않은 객체를 사용하여 한 경우 NullPointerException - Null 값을 허용하지않은 메서드에 null를 건넨 경우 .. 더보기
item 71) 필요 없는 검사 예외 사용은 피하라 1. Error vs Exception 2. unchecked vs checked 2-1 Unchecked Exception - RunTimeException 을 상속 받은 Exception - throw문이나 try catch 문으로 처리 해주지않아도됨. - RunTime 시점에서 발생하며, 예외 발생시 트랜잭션 롤백함 - NullPointerException, OutOfBoundsException 2-2 Checked Exception - RunTimeException을 상속 하지 않은 Exception 클래스들 - 명시적으로 Throw나 try-catch 문으로 처리해줘야 하고 처리하지 않으면 컴파이 ㄹ에러 발생 - 컴파일 시점에서 체크하며, 예외 발생시 트랜잭션 롤백하지 않음 - IOExcepti.. 더보기
item 62) 다른 타입이 적절하다면 문자열 사용을 피하라 문자열은 텍스트를 표현하도록 설계되었고, 자바에서도 잘 지원해줘서 다른 용도로 쓰이는 경우가 있음 1) 문자열은 다른 값 타입을 대신하기에 적합하지 않음 - 파일, 네트워크, 키보드 등으로부터 입력을 받을때 주로 문자열 타입으로 받는다. 그후에 타입을 명시적으로 변환한다. => 타입을 명시적으로 변환하는 것은 좋은 프로그래밍 코드가 아님.(ClassTypeException 및 변환 코드로 기존 코드가 더러워진다.) - 적절한 타입이 있다면 그 타입을을 사용하고 만약 없다면 새로운 타입을 작성하라. 2) 열거타입을 대신하기 어렵다. - 상수를 열거할떄는 열거타입을 사용하자.(변수의 범위를 제한할수 있다.) 3) 혼합타입을 대신하기 어렵다. - 여러 요소가 혼합된 데이터를 하나의 문자열로 표현하는 것은 좋지.. 더보기