개발서적

    [Effective Java] Serializable을 구현할지는 신중히 결정하라

    어떤 클래스의 인스턴스를 직려화할 수 있게 하려면 클래스 선언에 implements Serializable만 붙이면 된다. 직렬화를 하기는 정말 쉽지만, 길게 보면 아주 값비싼 일이다. Seriazliable의 다양한 문제 릴리스한 뒤에는 수정이 어렵다 클래스가 Serializable을 구현하면 직렬화된 바이트 스트림 인코딩(직렬화 형태)도 하나의 공개 API가 된다. 테스트할 것이 늘어난다. 모든 직렬화 된 클래스에는 고유 식별 번호를 부여 받는데, 이 번호는 클래스의 모든 정보를 고려한 해싱 방법으로 생성된다. (글자 하나만 달라져도 해시값이 달라진다) 버그와 보안에 위험이 생긴다 객체는 생성자를 만드는 게 기본이다. 하지만 역직렬화는 일반 생성자의 문제가 그대로 적용되는 '숨은 생성자'이다. 불변식..

    [Effective Java] 공유 중인 가변 데이터는 동기화해 사용하라

    동기화 synchronized 키워드는 해당 메서드나 블록을 한번에 한 스레드씩 수행하도록 보장해준다. 즉, 배타적 실행을 도와준다. 동기화는 일관성이 깨진 상태를 볼 수 없게하는 것은 물론, 동기화된 메서드나 블록에 들어간 스레드가 같은 락의 보호하에 수행된 모든 이전 수정의 최종 결과를 보게 해준다. 자바 언어 명세는 스레드가 필드를 읽을 때 항상 수정이 완전히 반영된 값을 얻는다고 보장하지만, 한 스레드가 저장한 값이 다른 스레드에게 보이는가는 보장하지 않는다. 스레드 간 통신 공유 중인 가변 데이터를 비록 원자적으로 읽고 쓸 수 있을지라도 동기화에 실패하면 처참한 결과를 얻을 수 있다. 예를 들어 스레드를 멈추는 작업을 생각해보자. public class StopThread { private st..

    [Effective Java] 예외를 무시하지 말라

    예외를 무시하지 말라 기본적이지만 많은 사람들이 예외를 무시하곤 한다. 다음과 같이 빈 catch()문을 사용함으로서 예외를 무시한다. try { ... } catch(SomeException e) { } 예외는 문제 상황에 잘 대처하기 위해 존재하는데 catch블록을 비워두면 예외가 존재할 이유가 없어진다. 물로 예외를 무시해야 할 때도 있다. 예를 들어 FileInputStream을 닫을 때가 그렇다. -> 파일의 상태를 변경하지 않았으니 복구할 것이 없으며, 스트림을 닫는다는 것은 필요한 정보는 이미 다 읽었다는 뜻이니 남은 작업을 중단할 이유도 없다. -> 이런 경우에도 파일을 닫지 못했다는 사실을 로그로 남기는 것이 좋다. 만약 예외를 무시하기로 했다면 catch블록 안에 그렇게 결정한 이유를 ..

    [Effective Java] 가능한 한 실패 원자적으로 만들라

    실패 원자적 성질 호출된 메서드가 실패하더라도 해당 객체는 메서드 호출 전 상태를 유지해야 한다. 이러한 특성을 실패 원자적이라고 한다. 메서드를 실패 원자적으로 만드는 방법 불변 객체로 설계한다. 메서드가 실패하면 객체가 생성되지 않을 수는 있으나 값은 생성 시점에 고정되어 절대 변하지 않는다. 작업 수행에 앞서 매개변수의 유효성을 검사한다. public Object pop() { if (size == 0) throw new EmptyStackException(); Object result = element[--size]; elements[size] = null; // 다 쓴 참조 해제 return result; } 이 메서드는 처음 if문에서 size의 값을 확인하여 0이면 예외를 던진다. 이 부분을..

    [Effective Java] 예외의 상세 메세지에 실패 관련 정보를 담으라

    자바의 스택 추적 예외를 잡지 못해 프로그램이 실패하면 자바 시스템은 그 예외의 스택 추적 정보를 자동으로 출력한다. 스택 추적은 예외 객체의 toString 메서드를 호출해 얻는 문자열로, 보통은 예외의 클래스 이름 위에 상세 메세지가 붙은 형태다. 따라서 toString 메서드에 실패 원인에 관한 정보를 가능한 한 많이 담아 반환하는 일은 아주 중요하다. 에러를 담당하는 Throwable 클래스의 생성자와 toString()메서드는 다음과 같이 되어 있다. public Throwable(Throwable cause) { fillInStackTrace(); detailMessage = (cause==null ? null : cause.toString()); this.cause = cause; } pub..