第4项:经过私有构造器强化不可实例化的能力

  有时候你会想要编写一个只包含一组静态方法和静态字段的类。这种类名声很很差,由于有些人为了不使用面向对象的思惟方式而滥用这样的类(some people abuse them to avoid thinking in terms of objects),可是他们确实有它们特有的用处。咱们可使用这种类,以java.lang.Math或者 java.util.Arrays的方式对原始值或数组的相关方法组织起来。它们还能够用于以java.util.Collections的方式,把实现特定接口的对象上的静态方法(包括工厂:第1项)组织起来。(从Java 8开始,你也能够将这些方法放在接口中,假设它是你本身修改的)。最后,这些类能够用于对final类的方法组织起来,经过这种方式用以取代扩展该类的作法。java

  这种工具类不但愿被实例化,实例化对它没有任何意义。然而,在没有显式构造函数的状况下,编译器会默认提供一个公共的、无参的默认构造函数。对于用户而言,这个构造器与其余构造器没有任何区别。在已发行的API中经常能够看到一些被无心识地实例化的类。数组

  企图经过将该类作成抽象类来强制该类不可被实例化,这是行不通的。该类能够被子类化,而且该子类也能够被实例化。这样作甚至会误导用户,觉得这种类是专门为了继承而设计的(第19项)。然而,有一些简单的习惯用法能够确保类不可被实例化。因为只有当类不包含显示的构造器时,编译器才会生成缺省的构造器,所以咱们只要让这个类包含私有构造器,他就不能被实例化了:函数

// Noninstantiable utility class
public class UtilityClass {
    // Suppress default constructor for noninstantiability
    private UtilityClass(( {
        throw new AssertionError();
    }
    ... // Remainder omitted
}

  由于显示构造函数是私有的,因此它在类外是不可访问的,AssertionError不是必需的,可是它能够避免不当心在类的内部调用构造器。它保证该类在任何状况下都不会实例化。这种习惯用法有点违背直觉,好像构造器就是专门设计成不能被调用同样。所以明智的作法就是在代码中增长一条注释,如上所示。工具

  这种习惯用法也有反作用,它使得一个类不能拥有子类。由于子类的全部构造函数都必须显示或者隐式地调用父类的构造函数,在这种情形下,子类就没有可访问的父类构造器可用了。spa

我的公众号同步更新

相关文章
相关标签/搜索