[이펙티브 자바] 6. 불필요한 객체 생성을 피하라

노을·2023년 1월 17일
0

이펙티브 자바

목록 보기
6/14
post-thumbnail

⭐ 불필요한 객체를 생성하는 경우 & 해결방법



☑️ 무분별한 String 객체 생성


String s = new String("bikini");

이렇게 newString 객체 생성을 하는 경우엔 이 문장이 실행될 때 마다 새로운 객체가 만들어진다.

String s1 = new String("bikini");
String s2 = new String("bikini");

System.out.println("s1 equals s2 " + s1.equals(s2)); //true
System.out.println("s1 == s2 " + s1 == s2); //false

s1s2는 값도 같고 기능적으로 동일하지만 s1 == s2 했을 때 false가 나온다.


이를 해결하기 위해서는 값이 같다면 하나의 인스턴스를 사용하면 된다.

String s1 = "bikini";
String s2 = "bikini";

System.out.println("s1 equals s2 " + s1.equals(s2)); //true
System.out.println("s1 == s2 " + s1 == s2); //true

이렇게 하면 같은 객체를 재사용할 수 있게 된다.



☑️ 팩터리 메서드가 있는데 생성자를 사용하는 경우

Boolean aBoolean = new Boolean("hello"); //사용자제 API

처럼 Boolean 생성자로 객체를 만들 수 있지만
불필요한 객체 생성을 방지하기 위해 Boolean.valueOf(String string)을 사용하자.

Boolean aBoolean = Boolean.valueOf("hello");



☑️ 생성 비용이 비싼 객체를 반복해서 쓰는 경우

생성 비용이 비싼 객체가 있다면 캐싱해서 사용해야 한다.

예를 들면 String.matches 메서드가 있다.

static boolean isRomanNumeralSlow(String s) {
    return s.matches("^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
}

s.matches를 실행하면 Pattern 인스턴스가 만들어지는데 한 번 쓰여지고 버려진다.


이를 해결하기 위해 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 isRomanNumeralFast(String s) {
    return ROMAN.matcher(s).matches();
}



☑️ 오토박싱

오토 박싱 : 기본 타입과 박싱된 기본 타입을 섰어 쓸 때 자동으로 상호 변환해주는 기술

private static long sum() {
    Long sum = 0L; //sum은 long이 아니라 Long 타입
    for (long i = 0; i <= Integer.MAX_VALUE; i++)
        sum += i;
    return sum;
}

현재 sumlong이 아니라 Long 타입이기 때문에 sum += i이 실행될 때 마다 Long 객체가 새로 만들어지고 있는 것이다. 총 Long 객체는 Integer.MAX_VALUE 만큼 만들어졌다.
➡️ 기본 타입을 사용하자!



⭐ 주의할 점

객체 생성을 무조건 피해야 한다고 생각하지 말자.
요즘 JVM 가비지 컬렉터는 최적화가 잘 되어 있어서 억지로 객체 풀을 만드는 것은 바람직하지 못하다. 자체 객체 풀은 코드를 헷갈리게 만들고 메모리 사용량을 늘리며 성능을 떨어뜨리기 때문에 조심해서 사용하자!

profile
진짜를 알면 곁가지를 몰라도 된다

0개의 댓글

관련 채용 정보