본문 바로가기

분류 전체보기

(214)
[아이템 11] equals를 재정의하려거든 hashCode도 재정의하라 [Why] equals를 재정의한 클래스에서 hashCode를 재정의하지 않으면 hashCode의 일반 규약을 어기게 되어 해당 클래스의 인스턴스를 HashMap, HashSet 같은 컬렉션의 원소로 사용할 때 문제를 일으킬 것이다. [When] Object 명세에서 발췌한 규약 equals 비교에 사용되는 정보가 변경되지 않았다면, 애플리케이션이 실행되는 동안 그 객체의 hashCode 메서드는 몇 번을 호출해도 일관되게 항상 같은 값을 반환해야 한다. 단, 애플리케이션을 다시 실행한다면 이 값이 달라져도 상관없다. equals(Object)가 두 객체를 같다고 판단했다면, 두 객체의 hashCode는 똑같은 값을 반환해야 한다. equals(Object)가 두 객체를 다르다고 판단했더라도, 두 객체의..
[아이템 10] equals는 일반 규약을 지켜 재정의하라 [Why] equals 규약을 어기면 그 객체를 사용하는 다른 객체들이 어떻게 반응할지 알 수 없다. Object 명세에 적힌 규약 equals 메서드는 동치관계(equivalence relation)을 구현하며, 다음을 만족한다. 반사성(reflexivity): null이 아닌 모든 참조 값 x에 대해, x.equals(x)는 true다. 대칭성(symmetry): null이 아닌 모든 참조 값 x, y에 대해, x.equals(y)가 true면 y.equals(x)도 true다. 추이성(transitivity): null이 아닌 모든 참조 값 x, y, z에 대해, x.equals(y)가 true이고 y.equals(z)도 true면 x.equals(z)도 true다. 일관성(consistency):..
[아이템 9] try-finally보다는 try-with-resources를 사용하라 [Why] 자바 라이브러리에는 close 메서드를 호출해 직접 닫아줘야 하는 자원이 많다. InputStream, OutputStream, java.sql.Connection 등 전통적으로 자원이 제대로 닫힘을 보장하는 수단으로 try-finally가 쓰였다. // 자원이 둘 이상이면 try-finally 방식은 너무 지저분하다! static void copy(String src, String dst) throws IOException { InputStream in = new FileInputStream(src); try { OutputStream out = new FileOutputStream(dst); try { byte[] buf = new byte[BUFFER_SIZE]; int n; while ..
[아이템 8] finalizer와 cleaner 사용을 피하라 [Why] finalizer는 예측할 수 없고, 상황에 따라 위험할 수 있으니 기본적으로 '쓰지 말아야' 한다. cleaner 역시 예측할 수 없고, 느리고, 일반적으로 불필요하다. finalizer 동작 중 발생한 예외는 무시되며, 처리할 작업이 남았더라도 그 순간 종료된다. 보통의 경우에는 예외가 발생하여 스택 추적 내역을 출력하겠지만, finalizer에서는 경고조차 출력되지 않는다. finalizer와 cleaner는 성능도 심각하다. 가비지 컬렉터보다 50배 정도 느리다. finalizer를 사용한 클래스는 finalizer 공격에 노출되어 심각한 보안 문제를 일으킬 수도 있다. 생성자나 직렬화 과정에서 만들어지다 만 객체를 악용할 수 있다. [When] 파일 닫기 finalizer와 clean..
[아이템 7] 다 쓴 객체 참조를 해제하라 [Why] 자바처럼 가비지 컬렉터를 갖춘 언어는, 다 쓴 객체를 알아서 회수해가기 때문에 자칫 메모리 관리에 더 이상 신경을 쓰지 않아도 된다고 오해할 수 있는데, 절대 사실이 아니다. [When] public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { ..
[아이템 6] 불필요한 객체 생성을 피하라 [배경] 똑같은 기능의 객체를 매번 생성하기보다는 객체 하나를 재사용하는 편이 나을 때가 많다. 재사용은 빠르고 세련되다. 불변 객체아이템17은 언제든 재사용할 수 있다. [예시] 1. String // 나쁜 예 String s = new String("bikini"); // 좋은 예 String s = "bikini"; 나쁜 예는 실행될 때마다 String 인스턴스를 새로 만든다. 좋은 예를 사용하면 같은 가상 머신 안에서 이와 똑같은 문자열 리터럴을 사용하는 모든 코드가 같은 객체를 재사용함이 보장된다. 2. 정적 팩터리 메서드를 제공하는 불변 클래스 // 나쁜 예 Boolean(String)// Java9, Deprecated // 좋은 예 Boolean.valueOf(String) 생성자는 호출할..
Chapter 3. 애자일 프로젝트 계획 3.1 기존 개발 방법론은 어떻게 활용해야 하는가? [기존 개발 방법론들] 구조적 방법론 객체지향 RUP(Rational Unified Process) CBD(Component Based Development) SOA(Software Oriented Architecture) [프로젝트 관리 방법론들] PMBOK(Project Management Body Of Knowledge) CMMI(Capability Maturity Model Integration) [문제 의식] 복잡한 프로세스와 많은 산출물 때문에 프로젝트에서 따라 하기가 쉽지 않다. 이런 방법론들이 강조되는 이유는 좋은 프로세스대로 일하다보면 훌륭한 제품을 만들 수 있다는 가정이 깔려 있기 때문이다. 그래서 선도 기업(IBM, Google 등)..
[아이템 5] 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 [배경] 많은 클래스가 하나 이상의 자원에 의존한다. [(예시) 사전(dictionary에 의존하는 맞춤법 검사기] 1. 정적 유틸리티 클래스로 구현 public class SpellChecker { private static final Lexicon dictionary = ...; private SpellChecker() {} // 객체 생성 방지 public static boolean isValid(String word) { ... } public static List suggestions(String typo) { ... } } 2. 싱글턴으로 구현 public class SpellChecker { private final Lexicon dictionary = ...; private SpellChe..