객체를 관리하는 것은 메모리리를 효율적으로 사용하는 것으로 이어진다
때문에 불필요한 객체를 생성하지 않는 것이 좋다.
String s = new String("이러지 말자");
String s = "이러자";
위의 String은 스트링 객체를 생성하기 위해 문자열. 즉 스트링을 이용하고 있다.
객체를 생성하기 위해, 객체를 이용하고 있기에 메모리 낭비가 생긴다.
반복문 같은 곳에서 저런 코드를 사용하게 된다면 수백수천개의 객체가 생성될 수도 있다.
때문에 String 객체는 아래와 같은 방법으로 사용하는 것이 좋다.
Boolean bool = new Boolean("true");
Boolean bool2 = Boolean.valueOf("true");
Boolean 도 마찬가지이다.
생성자를 통하면 객체가 생성되므로
정적 팩토리 메소드가 있다면 이용하는 편이 현명하다.
위보다는 아래가 더 낫다.
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
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;
}
}
베이비 붐 시대에 태어난 사람이면
참을 반환하고 아니라면, 거짓을 반환하는 클래스이다.
이 코드에서 베이비 붐 시대라는 정의는 이 클래스가 호출 될 때마다 수행한다.
Calendar 객체 하나 TimeZone 객체 하나 Date 객체 두개를 쓸데없이 만들어낸다.
이런 코드는 static 처리를 통해서 효휼화가 가능하다.
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
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;
}
}
이런 식으로 정적 처리를 해주면
한번 호출 되어 객체를 생성한뒤, 불필요하게 반복적으로 객체를 생성하지 않기 때문에
효율적이다. Person 클래스가 자주 호출되는 클래스일 수록 결과는 크게 차이가 날 것이다.
하지만 이 코드는 재사용이 가능한 코드이기에 이런 방법이 가능했다. 코드별로 역할을 확인하고 적용해야할 것이다.
이 것 이외에도 JDK 1.5 부터 불필요한 객체를 생성하는 방법이 또 하나 생겼다.
자바의 기본형과, 그에 대응하는 참조 자료형을 섞어서 쓸 수 있게 된것이다.
먼저 아래 이미지를 보자
그림판으로 작업해서 좀 엉성하지만.. 자바에서 사용되는 변수 형태를 정리했다.
원시타입(primitive)에는 그에 대응하는 참조 자료형이 있다.
int i = 1; // primitive type
Integer i2 = new Integer(2); // reference type
이 둘의 차이점은 먼저 원시타입은 값만 가지지만, 참조 자료형은 아이덴티티도 가진다는 점과, 시간, 공간 효율적인 부분에서 기본 자료형이
더 효율성을 갖는 다는 차이가 있다.
한마디로 참조자료형이 더 덩치가 크다
1.5 버전 이후 이러한 원시타입(기본 자료형)과 참조자료형을 섞어서 써도 되게 되었다.
이 것을 자동 객체화(autoboxing)라고 부른다
아래 코드를 한번 봐보자
Long sum = 0L;
for(long i = 0; i < Integer.MAX_VALUE; i++){ // 2147483647
sum += i;
}
이러한 코드는 계산 성능이 매우 안좋다.
long(기본 자료형)으로 써야할 곳에 Long(참조 자료형) 알파벳 하나를 잘못 쓴 덕분이다.
덕분에 sum이 이용될 때마다 Long 객체가 만들어져서 2147483647개의 Long 객체가 생성된다.
이 코드는 Long sum 을 long sum으로 고쳐주면 성능이 크게 향상될 것이다.
여기서 얻을 수 있는 교훈은 객체 표현형 대신 기본자료형을 사용하고,
자동 객체화가 발생되어 작업량을 늘리는 일을 피하는 것이 바람직하다는 것이다.
'프로그래밍 > Java' 카테고리의 다른 글
이펙티브 자바 규칙 6 - 유효기간이 지난 객체는 폐기하자 (0) | 2018.01.30 |
---|---|
이펙티브 자바 규칙 4 - 객체 생성은 private 생성자로 막자 (0) | 2018.01.27 |
이펙티브 자바 규칙 3 - 싱글톤 (0) | 2018.01.27 |