Item 6 - 불필요한 객체 생성을 피하라
객체의 재사용
똑같은 기능의 객체를 매번 생성하는 것보다 객체 하나를 재사용하는 편이 나을 때가 많다.
- 생성자 대신 정적 팩터리 메서드를 사용하여 불필요한 객체 생성을 피할 수 있다.
- ex) Boolean(String) 대신 Boolean.valueOf(String)
생성 비용이 아주 비싼 객체일 경우
String.matches
로 정규표현식을 통해 문자열 형태를 확인하는 코드
1
2
3
4
5
static boolean isRomanNumeral(String s) {
// String.matches 내부에서 새로운 Pattern 인스턴스를 생성
return s.matches("^(?=.)M*(C[MD]|D?C{0,3})"
+ "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
}
- 메서드 내부에서 만드는 Pattern 인스턴스는 한번 쓰고 버려지므로 가비지 컬렉션 대상이 된다.
- 성능이 중요한 상황에서 반복해서 사용하기에 적합하지 않다.
1
2
3
4
5
6
7
8
9
10
11
// 값비싼 객체를 재사용해 성능을 개선한다.
public class RomanNumerals {
// 인스턴스 생성비용이 높은 Pattern 인스턴스를 미리 생성해두고, 해당 인스턴스를 재사용
private static final Pattern ROMAN = Pattern.compile(
"^(?=.)M*(C[MD]|D?C{0,3})"
+ "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
static boolean isRomanNumeral(String s) {
return ROMAN.matcher(s).matches();
}
}
성능개선을 위해 Pattern 인스턴스를 클래스 초기화 과정에서 생성하여 캐싱해두고,
isRomanNumeral
메서드가 호출될 때마다 재사용하자.
어댑터 (view)
실제 작업은 뒷단 객체에 위임한 채, 자신은 제 2의 인터페이스 역할을 하는 객체
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class AdapterExample {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("one", 1);
map.put("two", 2);
Set<String> keys1 = map.keySet();
Set<String> keys2 = map.keySet();
// 반환받은 Set 객체 중 하나를 수정하면 다른 모든 객체도 따라서 수정된다.
keys1.remove("one");
System.out.println(keys2.size()); // 1
System.out.println(map.size()); // 1
}
}
어댑터는 뒷단 객체 하나당 어댑터 하나씩만 만들어지면 충분하다.
- 예컨대, Map 인터페이스가 제공하는
keySet
메서드는 Map 객체 안의 키 전부를 담은 Set뷰를 반환한다. keySet
을 호출할 때마다 새로운 객체가 만들어질 것 같지만 사실 같은 객체를 반환한다.- 즉, 반환된 객체 중 하나를 수정하면 다른 모든 객체가 따라서 바뀐다.
- (모두가 같은 Map 인스턴스를 대변하기 때문)
- 반환된 Set 객체가 일반적으로 가변이더라도 반환된 객체들은 기능적으로 모두 똑같다.
- 따라서
keySet
이 뷰 객체를 여러 개 만드는 건 불필요하다.
오토박싱 (auto boxing)
기본 타입과 박싱된 기본 타입을 섞어 쓸 때 상호 변환해주는 기술
1
2
3
4
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++) {
sum += i;
}
- 타입의 구분을 완전히 없애주는 것은 아니어서 성능에 영향을 준다.
- sum 변수를 long이 아닌 Long으로 선언했기 때문에 성능이 훨씬 느려짐.
- long 타입인 i가 Long 타입인 sum에 더해질 때마다 불필요한 Long 인스턴스가 만들어지므로.
박싱된 기본 타입보다는 기본 타입을 사용하도록 하고, 의도치 않은 오토박싱이 있는지 주의하자.
참고 🕶️
자바 정규표현식 Pattern 문법
https://docs.oracle.com/javase/tutorial/essential/regex/
https://regex101.com/ 또는 https://regexr.com/
가비지 컬렉션
https://developers.redhat.com/articles/2021/11/02/how-choose-best-java-garbage-collector#
This post is licensed under CC BY 4.0 by the author.