[Effective Java] item4 - 인스턴스화를 막으려거든 private 생성자를 사용하라

신민철·2023년 4월 9일
1

Effective Java

목록 보기
4/23
post-thumbnail

정적 메소드와 정적 필드만 가진 클래스를 살펴보자.

객체지향에서는 욕을 먹을 방법이지만, 쓸데는 있을 것이다. (java.lang.Math, java.lang.Arrays) 그리고 final 클래스와 관련한 메소드를 모을 때도 final 클래스를 상속해서 하위 클래스 메소드에 넣는 건 불가능하기에 별개의 클래스로 빼기도 한다.

이러한 클래스들은 인스턴스를 만들어 사용하려는 클래스가 아닌데 일반적으로 생성자를 명시하지 않으면 기본 생성자가 만들어져 인스턴스를 생성할 수 있는 환경이 자동으로 생기게 된다! → 위험하다

추상 클래스는 이것을 방지해줄까? 한번 살펴보자.

public abstract class Test {

	public int checkTest() {
		return 1;
	}
}
public class NotTest extends Test {
	public NotTest() {
	}
}

일반적으로 추상 클래스는 확장되므로 해당 클래스를 사용하는 클라이언트 입장에서는 확장을 해서 사용하라는 의미로 받아들이는게 정상일 것이다!

이를 방지하려면 애초에 생성자의 접근자를 private으로 막아두는 것이다.

public final class Math {

    private Math() {}
}
public class Arrays {

    // Suppresses default constructor, ensuring non-instantiability.
    private Arrays() {}
}

위의 코드는 java.util.Math와 java.util.Array 클래스이다.

두 클래스의 공통점이 보면 둘 다 인스턴스를 생성하지 않고 사용하는 클래스이다. 그러므로 생성자를 모두 private 접근자로 인스턴스를 생성하지 못하도록 막아 둔 것이다!

그런데 클래스 내부나 리플렉션을 통해 생성되는 걸 2차로 막기 위해서 AssertionError까지 던지게 만들 수도 있다. 근데 생성하는데 에러가 난다고 생각하면 이상하므로 주석까지 달아주는 것이 정석일 것이다!

핵심 정리
인스턴스화를 막기 위해선 생성자의 접근자를 private으로 막아둬라! 그러면 상속을 받아도 인스턴스를 생성하지 못할 것이다.

0개의 댓글