Programming/Java

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

VSFe 2021. 1. 25. 20:14
인스턴스화를 막으려거든 private 생성자를 사용하라!

정적 메소드와 정적 필드'만' 담은 클래스를 만들어보자.

솔직히 객체지향에서 이러면 욕먹기 딱 좋지만, 그런데 쓸데는 있을 것이다. (ex. java.lang.Math) 그리고 final 클래스와 관련한 메소드를 모을때도 상속해서 사용하는 것은 불가능하니 별개의 클래스로 빼기도 한다.

당연히 이런 클래스는 인스턴스를 만들어서 쓰려고 설계한게 아닌데... 일반적으로 생성자를 명시하지 않으면 자연스럽게 기본 생성자가 만들어진다. 이러면 의도치 않은 작업이 발생할 수 있으니 매우 위험하다!

그래서 그 대안으로 추상 클래스를 만들었다!

public abstrct class test {
	public int Iamfree() {
		return 1;
	}
}

완벽하다고 생각하는 당신. 그런 당신을 위해 상속을 드립니다.

public class NotTest extends test {
	public NotTest() {
		// Some Code...	
	}
}

일반적인 추상 클래스는 확장을 하는 경우가 많으므로, 해당 클래스를 사용하는 클라이언트 입장에서는 확장을 해서 사용을 할 가능성이 높아진다. 그러니 아예 클래스 생성자를 막아버릴 생각이라면...

public class PreventedTest {
	private PreventedTest() {
		throw new AssertionError();
	}
}

클래스 내부나, 리플렉션을 통해 생성되는걸 2차로 막기 위해 AssertionError까지 던지게 만든다. 그러나 이렇게 보면 "생성자가 있는데 왜 에러가 나?" 라고 생각할 수 있으니 주석을 달아주면 좋을 것이다.

또한 의도하던 의도하지 않았던, final 마냥 상속도 막아버릴 수 있다. 모든 생성자는 명시적이나 묵시적으로 상위 클래스의 생성자를 호출하는데, 이런 상황에서 private로 선언했으니 당연히 막힐 수 밖에 없다.

 

분량이 짧아서 금방 해냈다. 가끔은 이렇게 힐링도 해야지...