객체의 생성과 파괴 - 인스턴스화를 막으려거든 private 생성자를 사용하라

풀어갈 나의 이야기·2023년 8월 16일
0

이팩티브자바

목록 보기
4/6
post-thumbnail

🔗 아이템 4. 인스턴스화를 막으려거든 private 생성자를 사용하라

static 메서드와 static 필드만을 담은 유틸리티 클래스는 객체 지향과 거리도 멀지만, 쓰임새가 있다. 하지만, 해당 클래스를 abstract로 만들어도, 상속 받아서 인스턴스를 만들 수 있기 때문에 인스턴스를 만드는 걸 막을 순 없다.

아무런 생성자를 만들지 않은 경우에도 컴파일러가 기본적으로 아무 인자가 없는 public 생성자를 만들어주기 때문에 그런 경우에도 인스턴스를 만들 수 있다.

따라서 인스턴스화를 막기 위해선 명시적으로 private 생성자를 추가해야 한다.

(참고, Spring에서 Utility class를 만들기 위해선 주로 abstract로 선언하고 있음. 상속해서 생성자를 만들어봤자, 그 생성자로 생성한 인스턴스로 Utility class의 멤버에 접근할 수 없음)

💎 정적 메서드와 정적 필드만을 담은 유틸리티 클래스의 예시

  • java.lang.Math, java.util.Arrays
  • java.util.Collections
    특정 인터페이스를 구현하는 객체를 생성해주는 정적 메서드(혹은 팩터리) 모음
  • final 클래스와 관련한 메서드들의 모음
    (final 클래스를 상속해 하위 클래스에 메서드를 넣는 건 불가능하기 때문)

이와 같이 정적 멤버만 담은 유틸리티 클래스는 인스턴스로 만들어 쓰려고 설계한 게 아니다.
but, 생성자를 명시하지 않으면 컴파일러가 자동으로 기본 생성자(매개변수 없는 public)를 만들어준다.

💎 인스턴스화 막기

  • 추상 클래스로 만드는 것으로는 인스턴스화를 막을 수 없다.
    → 하위 클래스를 만들어 인스턴스화 하면 그만이다.
    → 추상 클래스를 본 사용자도 상속해서 쓰라는 뜻으로 오해할 수 있다.

private 생성자를 추가하면 클래스의 인스턴스화를 막을 수 있다.

인스턴스를 만들 수 없는 유틸리티 클래스

public class UtilityClass {
	// 기본 생성자가 만들어지는 것을 막는다(인스턴스화 방지용)
	private UtilityClass() {
		throw new AssertionError(); // 생성자 내부 호출 시 명시적인 에러 던지기
	}
	...
}
  1. 명시적 생성자가 private
    → 클래스 바깥에서 접근할 수 없다.
    Assertion Error를 던져 클래스 안에서 실수로라도 생성자를 호출하지 않도록 해준다.
    이 코드는 어떤 환경에서도 클래스가 인스턴스화되는 것을 막아준다.
  2. 상속을 불가능하게 하는 효과가 있다.
    private으로 생성자를 선언했으니 하위 클래스가 상위 클래스의 생성자에 접근할 길이 막혀버린다.
profile
깨끗한 스케치북 일수록 우아한 그림이 그려지법, 읽기 쉽고, 짧은 코드가 더 아름다운 법.. 또한 프로그래머의 개발은 구현할 프로그래밍이 아닌, 풀어갈 이야기로 써내려가는것.

0개의 댓글