자바에는 InputStream, OutputStream, java.sql.Connection과 같은 직접 닫아줘야 하는 자원들이 존재합니다. 이 자원들을 제대로 닫지 않으면 메모리 누수와 같은 심각한 문제를 초래할 수 있습니다. 📌 실수를 유발할 수 있는 기존 코드 자바에서는 자원을 사용한 후 반드시 해제해야 하므로, 이전에는 try-finally를 사용하여 자원을 해제하는 방식이 흔했습니다. 하지만 이 방식은 복잡하고 오류를 유발할 가능성이 있습니다. 1 2 3 4 5 6 7 8 9 static String firstLineOfFile(String path) throws IOException { BufferedReader br = new BufferedReader(new FileReader(path)); try { return br....
Effective Java 3E Chapter 01
[아이템 8] finalizer와 cleaner 사용을 피하라
1. finalizer와 cleaner란? 자바에서는 객체 소멸 시 특정 작업을 수행하는 두 가지 방법, finalizer와 cleaner를 제공합니다. finalizer는 Java 9부터 deprecated로 지정되었으며, cleaner는 그 대안으로 제공되지만 여전히 예측 불가능하고 성능 문제가 있습니다. 2. finalizer와 cleaner의 문제점 2.1 언제 실행될지 알 수 없다 finalizer와 cleaner는 즉시 실행된다는 보장이 없습니다. 이들은 가비지 컬렉션이 수행될 때 동작하지만, 그 시점을 예측할 수 없기 때문에 시간에 민감한 작업을 이들에 의존할 수 없습니다. 2.2 finalizer의 느린 실행 finalizer는 lazy하게 실행됩니다....
[아이템 7] 다 쓴 객체 참조를 해제하라
1. 메모리 누수가 발생하는 예시 코드 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 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() { if (size == 0) throw new EmptyStackException(); return elements[--size]; // 메모리 누수 발생 가능 } private void ensureCapacity() { if (elements....
[아이템 6] 불필요한 객체 생성을 피하라
객체를 생성할 때 기능이 동일한 객체를 매번 새로 생성하기보다는 객체를 재사용하는 것이 성능과 메모리 효율성 측면에서 더욱 적절합니다. 특히 **불변 객체(immutable objects)**는 항상 재사용이 가능하므로 이를 적극 활용해야 합니다. 📌 문자열 생성 방법 객체 생성 방식 - 피해야 되는 예시 1 String str = new String("hello"); 이 방식은 매번 새로운 객체를 생성합니다. 같은 문자열을 사용하더라도 매번 새로운 인스턴스가 만들어져 낭비가 발생합니다. 리터럴 방식 1 String str = "hello"; 이 방식은 리터럴을 사용하여 JVM이 동일한 문자열을 캐싱하므로, 이미 같은 문자열이 있다면 이를 재사용합니다....
[아이템 5] 자원을 직접 명시하지 말고 의존객체를 주입을 사용하라
대부분의 클래스는 하나 이상의 리소스에 의존합니다. 이를 처리하는 방식에 따라 코드의 유연성과 테스트 가능성이 크게 달라집니다. 이번 포스트에서는 이러한 의존성 처리의 잘못된 방식과 올바른 방식을 비교하고, 의존성 주입을 통한 해결 방법을 소개합니다. 부적절한 구현 📌 정적 유틸리티를 잘못 사용한 예 1 2 3 4 5 6 7 8 9 10 public class SpellChecker { private static final Lexicon dictionary = ...; private SpellChecker() {} // 객체 생성 방지 public static boolean isValid(String word) { ....