사소하지만 중요한 객체 생성에 관한 내용이다. 그동안 별 생각없이 생성자를 호출해 객체를 만들어 사용해왔는데, 이는 마땅히 다른 대안, 방법이 없어서 그래왔었다. 그러다보니 어플리케이션이 느려지기 다반사였다. 아직 실제로 적용은 해보지 못했지만, 확실히 효율적인 방식임에는 이견이 없어 포스트를 작성한다.
불필요한 객체는 만들지 말라
아래는 절대로 피해야할 극.단.적인 예시 코드이다.
1 | String s = new String("문자열"); | cs |
위 코드는 아래 코드로 대체되는데, 위 코드는 실행될 때마다 String 객체를 만들어낸다. 반면, 아래 코드는 새로운 객체를 만드는 대신 동일한 String 객체를 사용한다.
1 | String s = "문자열"; | cs |
좀 더 실재하는 코드를 보자면 다음과 같다. 아래 코드의 isBabyBoomer() 메서드는 호출될 때마다 Calendar 객체 하나, TimeZone 객체 하나, Date 객체 두 개를 만들어낸다. 만약 반복문안에서 이 메서드를 호출한다면? 속도는 보장할 수 없다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class Person { private final Date birthDate; public boolean isBabyBoomer() { Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0); Date boomStart = gmtCal.getTime(); gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0); Date boomEnd = gmtCal.getTime(); return birthDate.compareTo(boomStart) >= 0 && birthDate.compareTo(boomEnd) < 0; } } | cs |
이렇게 비효율적인 코드는 정적 초기화 블록을 통해 개선할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class Person { private final Date birthDate; private static final Date BOOM_START; private static final Date BOOM_END; static { Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0); BOOM_START = gmtCal.getTime(); gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0); BOOM_END = gmtCal.getTime(); } public boolean isBabyBoomer() { return birthDate.compareTo(BOOM_START) >= 0 && birthDate.compareTo(BOOM_END) < 0; } } | cs |
개선된 위 코드는 Calendar, TimeZone, Date 객체를 클래스가 초기화 될 때 한 번만 만든다. isBabyBoomer() 메서드가 많이 호출되면 될수록, 향상된 성능을 체감할 수 있다. 게다가 성능 뿐만 아니라 코드도 간결해졌음을 알 수 있다.
객체의 표현형 대신 기본 자료형을 사용하고, 생각지도 못한 자동 객체화가 발생하지 않도록 유의하라
반응형
'☕️ JAVA' 카테고리의 다른 글
Spring AOP와 AspectJ 비교하기 (14) | 2019.12.15 |
---|---|
이미지를 BLOB 형태로 DB에 저장하기 (5) | 2018.09.09 |
웹 서버와 웹 어플리케이션 서버의 차이 (1) | 2017.12.22 |
예외(Exception) - 잘못된 처리들 (0) | 2017.12.04 |
[이펙티브자바] 규칙02 : 생성자 인자가 많을 때는 Builder 패턴을 고려하라 (0) | 2017.10.07 |