불필요한 객체 생성 피하기

반응형
728x90
반응형

String의 계속된 인스턴스 생성

자바 코드에서 만약, 하나의 객체의 기능이 반복이 될 경우 해당 객체와 같은 객체를 여러개 만드는 것보다 하나의 객체를 재사용하는 편이 낫다.

 

  • 잘못된 String 객체 생성
String s = new String("abd"); 

 

위 코드는 잘못된 코드이다. 문법 상으로는 문제가 없지만, 완전히 쓸데없는 행위이다. 생성자에 넘겨진 “abd” 자체와 생성자의 호출로 만들어지는 String 객체가 기능적으로 완전히 똑같기 때문이다. 위 코드 한줄이 반복문같은 여러번 호출되는 코드라면 String 인스턴스를 무의미하게 수백만개 만들 수 있다.

 

  • 하나의 String 인스턴스
String s = "abd"; 

 

위 코드 한줄로 String 인스턴스 s를 생성하였고, 만약 “abd”가 필요한 코드가 존재한다면 객체 s를 재사용 할 것이다. 생성자를 호출한다는 것은 객체를 생성한다는 것과 같다.

Boolean(String) 생성자 대신에, Boolean.valueOf(String) 팩터리 메서드를 사용하는 것이 좋다. Boolean 생성자는 deperecated 되었다.

 

생성자는 호출할때마다 새로운 객체를 만들지만, 팩터리 메소드는 그렇지 않다. 불변 객체만이 아니라 가변 객체라도, 사용중에 변경되지 않을 것임을 안다면 재사용 할 수 있다.

 

 

비싼 객체의 사용

코드를 짜다보면, 생성 비용이 비싼 객체가 존재한다. 우리는 이러한 객체가 성능에 연관이 있는지를 쉽게 파악할 수 없고 명확히 알 수 없다.

 

  • 예시) 정규표현식
static boolean test(String s) {     
	return s.matches("^(?=.)M*(C[MD]|......"); 
}

 

위 예시에서 String.matches를 사용하였다. String matches는 정규표현식으로 문자열 형태를 확인하는 가장 쉬운 방법이지만, 성능이 중요한 상황에서 반복해 사용하기엔 적합하지않다. 이러한 경우에는 정규표현식을 표현하는 불변 Patern 인스턴스를 클래스 초기화 과정에서 직접 생성해 캐싱해두고, 나중에 정규표현식이 필요할때 마다 호출하여 해당 인스턴스를 재사용하면 된다.

 

  • 정규표현식 Pattern 재사용
public class Test {
    private static final Pattern R = Pattern.compile("^(?=.).....);      "

    static boolean isTest(String s) {
        return R.matcher(s).matches();
    }
}

 

 

오토박싱의 불필요한 객체 생성

오토 박싱(auto boxing)도 불필요한 객체를 만들어내는 또다른 예시이다. 오토 박싱은 프로그래머가 기본 타입과 박싱된 기본 타입을 섞어 쓸때 자동으로 상호 변환해주는 기술이다.

 

오토박싱

private static long sum() {
    Long sum = 0L;
    for (long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
    }
}

 

위 코드는 매우 느리다. sum 변수를 long이 아닌 Long 으로 선언하였기 때문에 sum에 i가 더해질때마다 Long 타입 인스턴스를 계속해서 생성한다. 위 코드에서 sum을 long으로만 바꿔주면 성능이 매우 좋아질 것이다. 박싱된 기본 타입보다는, 기본타입을 사용하고 의도치않은 오토박싱을 사용하지 않도록 주의해야한다.

 

반응형

'Coding > Java' 카테고리의 다른 글

[JAVA] Map null값 체크하기  (0) 2019.02.15
src/resources 폴더 안의 파일 읽어오기  (0) 2018.10.30
전역변수 vs 멤버변수  (0) 2018.10.28
new 연산자를 사용하여 인스턴스 생성  (1) 2018.10.28
I/O Stream 스트림  (0) 2018.10.28

Designed by JB FACTORY