effectivejava(51)
-
[Item 78] 공유 중인 가변 데이터는 동기화해 사용하라
synchronized(동기화) 해당 메서드나 블록을 한 번에 한 스레드씩 수행하도록 보장한다. 한 객체가 일관된 상태를 가지고 생성되고, 이 객체에 접근하는 스레드가 락을 건다. 상태를 확인하고 필요하면 수정한다. 일관된 상태에서 다른 일관된 상태로 변화시키는 것이다. 그래서 동기화를 제대로 사용하면 항상 일관된 상태를 볼 수 있다. 위의 기능도 중요하지만 동기화의 중요한 기능이 하나 더 있다. 동기화 없이는 한 스레드가 만든 변화를 다른 스레드에서 확인하지 못할 수도 있다. 동기화는 일관성이 깨진 상태를 볼 수 없게 하는 것은 물론, 동기화된 메서드나 블록에 들어간 메서드가 같은 락의 보호하에 수행된 모든 이전 수정의 최종 결과를 보게 해 준다. long과 double 외의 변수를 읽고 쓰는 것은 원..
2022.09.26 -
[Item 77] 예외를 무시하지 말라
예외 명시 API 설계자가 메서드 선언에 예외를 명시하는 까닭은, 그 메서드를 사용할 때 적절한 조치를 취해달라고 말하는 것이다. 예외는 문제 상황에 잘 대처하기 위해 존재하는데 catch 블록을 비워두면 예외가 존재할 이유가 없어진다. (catch 블록을 비워두면 예외가 무시된다.) 예외의 무시 예외를 무시하기로 했다면 catch 블록 안에 그렇기 결정한 이유를 주석으로 남기고 예외 변수의 이름도 ignored로 바꿔놓도록 하자. try { numColors = f.get(1L, TimeUnit.SECONDS); } catch (TimeoutException | ExecutionException ignored) { ... } 예외를 무시하지 않고 바깥으로만 전파하게 놔둬도 최소한 디버깅 정보를 남긴 채..
2022.09.26 -
[Item 76] 가능한 한 실패 원자적으로 만들라
실패 원자적 호출된 메서드가 실패하더라도 해당 객체는 메서드 호출 전 상태를 유지하는 특성을 실패 원자적(failure-atomic)이라고 한다. 메서드를 실패 원자적으로 만드는 방법 불변 객체를 설계한다. 불변 객체는 생성 시점에 고정되어 절대 변하지 않기 때문에 기존 객체가 불안정한 상태가 빠지는 일은 없다. 로직을 수행하기 전에 매개변수의 유효성을 검사한다. 객체의 내부 상태를 변경하기 잠재적 예외의 가능성 대부분을 걸러낸다. public Object pop() { if (size == 0) throw new EmptyStackException(); Object result = elements[--size]; elements[size] = null; // 다 쓴 참조 해제 return result;..
2022.09.26 -
[Item 75] 예외의 상세 메시지에 실패 관련 정보를 담으라
예외를 잡지 못해 프로그램이 실패하면 자바 시스템은 그 예외의 스택 추적(stack trace) 정보를 자동으로 출력한다. 스택 추적은 예외 객체의 toString 메서드를 호출해 얻는 문자열로, 보통은 예외의 클래스 이름 뒤에 상세 메시지가 붙는 형태이다. 실패 순간을 포착하려면 발생한 예외에 관여된 모든 매개변수와 필드의 값을 실패 메시지에 담아야 한다. 예컨대, IndexOutOfBoundsException 의 상세 메시지는 범위의 최대, 최솟값과 범위를 벗어난 인덱스의 값을 담아야 한다. public IndextOutOfBoundsException(int lowerBound, int upperBound, int index){ // 실패를 포착하는 상세 메시지를 생성한다. super(String.f..
2022.09.25 -
[Item 69] 예외는 진짜 예외 상황에만 사용하라
예외의 사용 예외는 (그 이름이 말해주듯) 오직 예외 상황에서만 써야 한다. 절대로 일상적인 제어 흐름용으로 쓰여선 안된다. 잘 설계된 API라면 클라이언트가 정상적인 제어 흐름에서 예외를 사용할 일이 없게 해야 한다. 특정 상태에서만 호출할 수 있는 '상태 의존적' 메서드를 제공하는 클래스는 '상태 검사' 메서드도 함께 제공해야 한다. Iterator 인터페이스의 next와 hasNext가 각각 상태 의존적 메서드와 상태 검사 메서드에 해당한다. 상태 검사 메서드를 이용한 for 관용구 코드 for (Iterator i = collection.iterator(); i.hasNext(); ) { Foo foo = i.next(); //Something job... } (for-each도 내부적으로 has..
2022.08.21 -
[Item 68] 일반적으로 통용되는 명명 규칙을 따르라
철자 규칙은? 철자 규칙은 패키지, 클래스, 인터페이스, 메서드, 필드, 타입 변수의 이름을 다룬다. - 패키지와 모듈명은 각 요소를 점(.)으로 이으며 계층적으로 짓는다. 모두 소문자 혹은 숫자로 지어야 한다. 도메인이 있다면 역순으로 사용한다. 예컨대 com.google, org.eff, edu.cmu 식이다. 패키지 이름의 나머지는 해당 패키지를 설명하는 하나 이상의 요소로 이루어진다. 각 요소는 8자 이하의 짧은 단어로 한다. utilities 보다는 util 같은 약어를 추천한다. 또한, 여러 단어로 구성된 이름이라면 awt처럼 각 단어의 첫 글자만 따서 사용한다. - 클래스와 인터페이스 이름은 대문자로 시작하며 줄여 쓰지 않도록 한다. 대표적인 첫 글자만 딴 약자는 max, min이 있는데, ..
2022.08.21