기존 객체를 재사용할 수 있다면, 불필요하게 새 객체를 만들지 말고 재사용하라
불필요한 객체를 생성하는 예시
1. String 객체 매번 새로 만들기
객체가 매번 새로 생성될 뿐 아니라 같은 리터럴이더라도 객체가 같음을 보장할 수 없다.
// 부적합
String s1 = new String("bikini");
String s2 = new String("bikini");
System.out.println(s1 == s2); // false (서로 다른 객체)
// 적합
String s1 = "bikini";
String s2 = "bikini";
System.out.println(s1 == s2); // true (같은 객체)
2. 생성 비용이 비싼 객체 새로 만들기
matches 메서드는 내부적으로 입력받은 문자열을 Pattern 객체로 만든다.
Pattern 객체는 생성 비용이 비싸기 때문에 직접 생성하여 한 번만 컴파일하고 재사용하면 성능 개선에 좋다.
// 부적합
static boolean isRomanNueral (String s){
return s.matches("정규표현식");
}
// 적합
public static class RomanNumerals {
private static final Pattern ROMAN = Pattern.compile(
"정규 표현식");
static boolean isRomanNumeral(String s){
return ROMAN.mathcer(s).matches();
}
}
3. 어댑터 객체 여러개 만들기
어댑터(뷰) - 호환되지 않는 인터페이스를 가진 두 객체를 연결하는 객체
실제 작업은 뒷단 객체가 하기 때문에, 어댑터를 여러개 만들 필요 없다.
어댑터는 연결된 뒷단 객체 당 하나씩만 생성해도 충분하다.
예시) Map의 keySet 메서드
- 어댑터 - keySet 메서드 (Map 객체에서 key값만 뽑아서 Set으로 반환)
- 뒷단 객체 - Map, Set
즉 Map과 Set은 호환되지 않는 인터페이스이지만, Map의 키를 Set처럼 사용하게 해주는 어댑터 역할을 한다.
이때 KeySet을 호출할 때마다 새로운 Set 객체가 생성되는 것이 아니라
keySet에 의해 직접 참조한 Map의 key값이 감싸진 구조 (뷰 객체, 동기화 유지)이기 때문에 하나의 객체이다.
그렇기 때문에 keySet은 뷰 객체를 여러 개 만들 필요가 없다.
4. 오토 박싱
오토박싱 - 프로그래머가 기본타입과 박싱된 기본 타입을 섞어 사용할 때 자동으로 변환
private static long sum(){
Long sum = 0L;
for(long i = 0; i<=Integer.MAX_VALUE; i++){
sum+=i;
}
return sum;
}
sum을 Long 래퍼 클래스로 잘못 선언해서 기본 타입인 long과 같이 사용된 경우
의도치 않은 Long 객체가 많이 생성됨, 성능에 큰 영향을 준다.
박싱된 기본타입보다는 기본타입을 사용, 의도치 않은 오토박싱 주의
5. 객체 재사용의 단점
최근 JVM에게 객체 생성 회수가 큰 부담은 아니다.
따라서 아주 무거운 객체, 데이터 베이스 연결 등 경우가 아니라면 객체 생성을 굳이 피하지 않아도 된다.
⭐️ 오히려 객체 생성을 피하고, 재사용하는 과정에서 방어적 복사에 실패하면 얻는 버그, 피해가 생성 비용보다 더 크다.
'도서 > 이펙티브 자바' 카테고리의 다른 글
| [이펙티브 자바] 8. finalizer 와 cleaner 사용을 피하라 (0) | 2025.03.23 |
|---|---|
| [이펙티브 자바] 7. 다 쓴 객체 참조를 해제하라 (0) | 2025.03.21 |
| [이펙티브 자바] 5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) | 2025.03.04 |
| [이펙티브 자바] 4. 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) | 2025.03.03 |
| [이펙티브 자바] 3. private 생성자나 열거 타입으로 싱글턴임을 보증하라 (0) | 2025.02.22 |