Tips
《Effective Java, Third Edition》一书英文版已经出版,这本书的第二版想必不少人都读过,号称Java四大名著之一,不过第二版2009年出版,到如今已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深入的变化。
在这里第一时间翻译成中文版。供你们学习分享之用。java
偶尔你会想写一个类,它只是一组静态方法和静态属性。 这样的类得到了很差的名声,由于有些人滥用这些类而避免以面向对象方式思考,可是它们确实有着特殊的用途。 它们能够用来按照java.lang.Math
或java.util.Arrays
的方式,在基本类型的数值或数组上组织相关的方法。 它们也能够用于将静态方法(包括工厂(条目 1))分组,用于实现某个接口的对象,其方式为java.util.Collections
。 (从Java 8开始,你也能够将这些方法放在接口中,假如它是你本身修改的。)最后,这样的类能够用于在final类上对方法进行分组,由于不能将它们放在子类中。数组
这样的实用类( utility classes)不是设计用来被实例化的:一个实例是没有意义的。然而,在没有显式构造方法的状况下,编译器提供了一个公共的、无参的默认构造方法。对于用户来讲,该构造方法与其余构造方法没有什么区别。在已发布的 API中常常看到无心识的被实例的类。学习
试图经过建立抽象类来强制执行非实例化是行不通的。该类能够被子类化,子类能够被实例化。此外,它误导用户认为该类是为继承而设计的(条目 19)。不过,有一个简单的方法来确保非实例化。只有当类不包含显式构造方法时,才会生成一个默认构造方法,所以能够经过包含一个私有构造方法来实现类的非实例化:翻译
// Noninstantiable utility class public class UtilityClass { // Suppress default constructor for noninstantiability private UtilityClass() { throw new AssertionError(); } ... // Remainder omitted }
由于显式构造方法是私有的,因此在类以外是不可访问的。AssertionError
异常不是严格要求的,可是它提供了一种保证,以防在类中意外地调用构造方法。它保证类在任何状况下都不会被实例化。这个习惯用法有点违反直觉,好像构造方法就是设计成不能调用的同样。所以,如前面所示,添加注释是种明智的作法。设计
这种习惯有一个反作用,阻止了类的子类化。全部的构造方法都必须显式或隐式地调用父类构造方法,而子类则没有可访问的父类构造方法来调用。code