개인 유틸리티 클래스 생성자에서 사용할 수있는 선호하는 것은 무엇입니까?
-
29-08-2019 - |
문제
효과적인 Java (제 2 판), 항목 4에서는 개인 생성자를 사용하여 비 임계성을 시행하는 것에 대해 논의합니다. 다음은 책의 코드 샘플입니다.
public final class UtilityClass {
private UtilityClass() {
throw new AssertionError();
}
}
하지만, AssertionError
던질 옳은 것 같지 않습니다. API가 사용을 정의하는 방법입니다. AssertionError.
다른 것이 있습니까? Throwable
그것은 일반적 으로이 상황에 있습니까? 일반적으로 장군을 던지는 사람이 있습니다 Exception
메시지로? 아니면 관습을 작성하는 것이 일반적입니까? Exception
이것을 위해?
그것은 꽤 사소하지만, 나는 스타일과 표준 관점에서 그것에 대해 궁금한 점이 있다고 생각합니다.
해결책
"이 생성자가 결코 호출되지 않을 것이라고 주장하고있다"고 주장이있다. 그래서 실제로, AssertionError
여기에 맞습니다.
다른 팁
나는 Bloch의 의견을 포함하는 것을 좋아합니다.
// Suppress default constructor for noninstantiability
또는 더 나은 아직 오류에 넣습니다.
private UtilityClass()
{
throw new AssertionError("Suppress default constructor for noninstantiability");
}
UnsupportedOperationException 확인 된 예외는 더 나을 것이지만 컴파일 타임에 클래스를 잘못 인스턴스화하는 사람에게 경고 할 수 있기 때문에 확인 된 예외는 더 좋습니다.
는 어때 불법 세저러 ? :)
아니요 아니요, 조쉬 블로 치 (Josh Bloch)에 대한 모든 것을 존중합니다. 절대 던지지 마십시오 AssertionError
주장에서 나오지 않는 한. 여기에 AssertionError를 원한다면 assert(false)
. 그런 다음 코드를 읽는 사람이 나중에 찾을 수 있습니다.
더 좋은 점은 자신의 예외를 정의하십시오 CantInstantiateUtilityClass
. 그러면 당신은 말하는 코드가 있습니다
try {
// some stuff
} catch (CantInstantiateUtilityClass e) {
// react
}
포수의 독자가 알고 있습니다 무엇 일어난.
업데이트
너무나도 바보가 여기에 의해 방황하고 사실 이후 거의 4 년 후에 이것을 다시 내리게합니다. 따라서 표준에 주목하겠습니다 아직 정의합니다 AssertionError
실패한 주장의 결과로 일부 초보자가 생각하는 것이 아니라 영 잘 정의 된 유익한 예외 대신에 버려야합니다. 안타깝게도, 좋은 예외 징계는 아마도 Java 프로그래밍에서 가장 장려 된 기술 일 것입니다.
코드가 Maven 테스트 범위 내에서와 같은 종속성으로 주니트를 포함시킬 필요가있는 경우 <scope>test</scope>
, 곧바로 가십시오 Assertion.fail()
방법과 명확성이 크게 향상되어 이익을 얻습니다.
public final class UtilityClass {
private UtilityClass() {
fail("The UtilityClass methods should be accessed statically");
}
}
테스트 범위를 벗어난 경우 위와 같이 정적 가져 오기가 필요한 다음과 같은 것을 사용할 수 있습니다. import static pkg.Error.fail;
public class Error {
private static final Logger LOG = LoggerFactory.getLogger(Error.class);
public static void fail(final String message) {
LOG.error(message);
throw new AssertionError(message);
// or use your preferred exception
// e.g InstantiationException
}
}
다음 사용량.
public class UtilityClassTwo {
private UtilityClassTwo() {
Error.fail("The UtilityClass methods should be accessed statically");
}
}
가장 관용적 인 형태로, 그들은 모두 이것으로 요약됩니다.
public class UtilityClassThree {
private UtilityClassThree() {
assert false : "The UtilityClass methods should be accessed statically";
}
}
내장 예외 중 하나 인 UnsupportEdoperationException을 통해 '요청 된 작업이 지원되지 않는다'는 것을 나타낼 수 있습니다.
private Constructor() {
throw new UnsupportedOperationException(
"Do not instantiate this class, use statically.");
}
깨진 주장은 코드의 계약 사양을 끊었다는 것을 의미합니다. 그래서 여기가 옳은 일입니다.
그러나 인스턴스를 개인적으로 인스턴스화한다고 가정하면 다른 생성자가없는 한 생성자를 호출하고 오류가 발생합니까?
자신만의 클래스 확장을 만들 수 있습니다 Throwable
, EG :
class NoninstantiabilityError extends Throwable
여기에는 다음과 같은 장점이 있습니다.
- 이름은 문제를 나타냅니다
- 직접 확장되기 때문입니다
Throwable
우연히 잡힐 것 같지는 않습니다. - 직접 확장되기 때문입니다
Throwable
우연히 확인하고 각 생성자에게 전화를 걸어 예외를 잡아야합니다.
사용 예 :
public final class UtilityClass {
private UtilityClass() throws NoninstantiabilityError {
throw new NoninstantiabilityError();
}
...
}