在私有实用程序类构造函数中使用的首选Throwable是什么?

Effective Java(第二版) ,第4项,讨论使用私有构造函数来强制执行非实例化。 这是本书的代码示例:

public final class UtilityClass { private UtilityClass() { throw new AssertionError(); } } 

但是, AssertionError似乎不适合抛出。 没有任何东西被“断言”,这就是API如何定义AssertionError的使用。

在这种情况下,通常会有不同的Throwable吗? 通常只会抛出一个带有消息的常规Exception吗? 或者为此编写自定义Exception是常见的吗?

这是非常微不足道的,但我认为从forms和标准的角度来看,我只是对它感到好奇。

有一个断言:“我断言这个构造函数永远不会被调用”。 所以,确实, AssertionError在这里是正确的。

我喜欢包括Bloch的评论:

 // Suppress default constructor for noninstantiability 

或者更好,但把它放在错误中:

 private UtilityClass() { throw new AssertionError("Suppress default constructor for noninstantiability"); } 

UnsupportedOperationException听起来最合适,虽然检查exception会更好,因为它可能会警告某人在编译时错误地实例化该类。

IllegalAcessError怎么样? 🙂

不,不,对Josh Bloch充分尊重, 除非是来自AssertionError否则永远不会抛出AssertionError 如果你想在这里使用AssertionError,请使用assert(false)抛出它。 那么阅读代码的人可以在以后找到它。

更好的是,定义你自己的exception,比如CantInstantiateUtilityClass 。 然后你会有代码说

 try { // some stuff } catch (CantInstantiateUtilityClass e) { // react } 

这样捕手的读者才知道发生了什么

更新

每隔一段时间,一些该死的傻瓜就会在这里徘徊,并在事实发生近四年之后再次投票。 所以,我要注意,标准仍然AssertionError定义为AssertionError失败的结果,而不是某些初学者认为应该抛出一个明确定义的信息exception。 遗憾的是,良好的exception规则可能是Java编程中最不受鼓励的技能。

当代码要求将JUnit作为依赖项(例如在maven测试作用域test ,请直接使用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 // eg InstantiationException } } 

其中有以下用法。

 public class UtilityClassTwo { private UtilityClassTwo() { Error.fail("The UtilityClass methods should be accessed statically"); } } 

在最惯用的forms中,它们都归结为:

 public class UtilityClassThree { private UtilityClassThree() { assert false : "The UtilityClass methods should be accessed statically"; } } 

其中一个内置exception,可抛出UnsupportedOperationException以指示“不支持所请求的操作”。

  private Constructor() { throw new UnsupportedOperationException( "Do not instantiate this class, use statically."); } 

断言断言意味着您违反了代码的合同规范。 所以这是正确的。

但是,正如我假设你将私下实例化一个实例,它也会调用构造函数并导致错误 – 除非你有另一个构造函数?