자바에서 인스턴스를 생성하는 대표적인 방법은 new 키워드를 사용해 생성자를 호출하는 것이다.
기본적으로 파라미터가 없는 디폴트 생성자를 제공하며, 상황에 따라 파라미터를 추가해 다양한 생성자를 만들 수 있다.
이펙티브 자바 1장에서는 정적 팩토리 메서드를 소개한다.
처음 정적 팩토리 메서드란 표현이 낯설었는데 개념은 간단하다. 인스턴스를 반환하는 static method이다.
책에서 소개하는 정적 팩토리 메서드의 장점
1. 이름을 가질 수 있다.
생성자의 이름은 클래스명과 동일하게 만들어야 한다.
하지만 method는 다양하게 작명이 가능하고, 오버로딩을 통해 같은 이름의 메서드도 여러 개 만들 수 있다.
2. 호출될 때마다 인스턴스를 새로 생성하지 않아도 된다.
예로 Boolean.valueOf() 메서드이다.
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
매번 동일한 인스턴스를 생성하는 것은 GC의 대상이 되기 때문에 성능에 부하가 갈 수 있다.
위의 Boolean의 TRUE, FALSE 처럼 정적으로 인스턴스를 생성해 놓고 필요할 때마다 재활용(?)을 하게 되면 인스턴스를 생성과 GC의 비용을 들이지 않아도 된다.
3. 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 된다.
생성자는 생성자가 선언되어 있는 클래스의 인스턴스밖에 생성하지 못한다. 하지만 메서드는 반환 타입을 자유롭게 가질 수 있기 때문에 하위 타입 객체를 반환하도록 만들 수 있다는 것이다. 예는 4번과 같이 보면 된다.
4. 입력 매개변수에 따라 다른 클래스의 객체를 반환할 수 있다.
예로 EnumSet 클래스의 정적 팩토리 메서드인 of()를 보겠다.
of 메서드는 noneOf() 메서드의 반환 값을 반환한다. noneOf() 메서드는 universe.라는 배열의 길이에 따라 RegularEnumSet 클래스나 JumboEnumSet 클래스를 반환하게 되어 있다.
사용자 입장에서 EnumSet의 내부 구조를 알 필요 없이 of()라는 정적 팩토리 메서드를 사용하면 된다.
public static <E extends Enum<E>> EnumSet<E> of(E e) {
EnumSet<E> result = noneOf(e.getDeclaringClass());
result.add(e);
return result;
}
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
Enum<?>[] universe = getUniverse(elementType);
if (universe == null)
throw new ClassCastException(elementType + " not an enum");
if (universe.length <= 64)
return new RegularEnumSet<>(elementType, universe);
else
return new JumboEnumSet<>(elementType, universe);
}
5. 정적 팩토리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
책에서 소개하는 정적 팩터리 메서드의 단점
1. 상속을 하려면 public이나 protected 생성자가 필요하니 정적 팩터리 메서드만 제공하면 하위 클래스를 만들 수 없다.
상속의 조건은 public과 protected 생성자가 필요하다. 정적 팩터리 메서드만 가지고 인스턴스를 생성하고자 모든 생성자를 private한 클래스는 상속할 수 없다는 뜻이다. 책에선 아이템 18,17에서 설명하는 내용이 오히려 장점이 될 수 있다는데 일단 넘어가겠다.
2. 정적 팩토리 메서드는 프로그래머가 찾기 어렵다.
생성자는 클래스명으로 선언된 메서드를 찾으면 된다. 하지만 정적 팩토리 메서드는 일반 메서드와 형태가 같기 때문에 한눈에 찾기 어려울 수 있다. 따라서 문서를 잘 찾아보거나 작명 규약인 from, of, valueOf, instance, getInstance, create, newInstance, getType, newType, type과 같은 메서드를 보면 된다.
'Java > Effective Java' 카테고리의 다른 글
[아이템 6] 불필요한 객체 생성을 피하라 (0) | 2021.12.21 |
---|---|
[아이템 5] 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) | 2021.12.20 |
[아이템 4] 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) | 2021.09.30 |
[아이템 3] private 생성자나 열거 타입으로 싱글턴임을 보증하라 (0) | 2021.09.30 |
[아이템 2] 생성자에 매개변수가 많다면 빌더를 고려하라 (0) | 2021.09.28 |
댓글