在私有实用程序类构造函数中使用的首选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测试作用域
,请直接使用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."); }
断言断言意味着您违反了代码的合同规范。 所以这是正确的。
但是,正如我假设你将私下实例化一个实例,它也会调用构造函数并导致错误 – 除非你有另一个构造函数?