`

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

阅读更多
第4条:通过私有构造器强化不可实例化的能力

有时候,可能需要编写只包含静态方法和静态域的类。这些类的名声很不好,因为有些人滥用它们来避免从对象的角度进行思考,但是它们也确实有它们特有的用处。我们可以利用这种类,以java.lang.Math或者java.util.Arrays的方式,把基本类型的值或者数组类型上的相关方法组织起来。我们也可以通过java.util.Collections的方式,把实现特定接口的对象上的静态方法(包括工厂方法,见第1条)组织起来。最后,还可以利用这种类把final类上的方法组织起来,以取代扩展该类的做法。

这样的工具类(utility class)不是要被实例化的:实例没有任何意义。然而,在缺少显式构造器的情况下,编译器会自动提供一个公有的、无参的默认构造器(default constructor)。对于用户而言,这个构造器与其他的构造器没有任何区别。在已发行的API中常常可以看到一些被无意识地实例化的类。

企图通过将类做成抽象类来强制该类不可被实例化,这是行不通的。该类可以被子类化,并且该子类也可以被实例化。这样做甚至会误导用户,以为这种类是专门为了继承而设计的(见第17条)。然而,有一些简单的习惯用法可以确保类不可被实例化。由于只有当类不包含显式的构造器时,编译器才会生成默认的构造器,因此让类包含私有构造器,它就不能被实例化了:

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


由于显式的构造器是私有的,所以不可以在该类的外部访问它。AssertionError不是绝对必要,但是它可以避免不小心在类的内部调用构造器。它保证该类在任何情况下都不会被实例化。这种习惯用法有点违反直觉,好像构造器就是专门设计成不能调用一样。因此,明智的做法就是在代码中增加一条注释,如上所示。

这种习惯用法也有副作用,它使得一个类不能被子类化。所有的构造器都必须显式或隐式地调用超类(superclass)构造器,在这种情形下,子类就没有可访问的超类构造器来调用了。
分享到:
评论

相关推荐

    Java经典编程源码基础例程300.zip

    第4章 流程控制 25 实例019 判断某一年是否为闰年 26 实例020 验证登录信息的合法性 27 实例021 为新员工分配部门 28 实例022 用switch语句根据消费 金额计算折扣 29 实例023 判断用户输入月份的季节 31 实例024 ...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    第4章 字符串处理技术 75 4.1 格式化字符串 76 实例060 把数字格式化为货币字符串 76 实例061 格式化当前日期 77 实例062 货币金额大写格式 78 实例063 String类格式化当前日期 80 实例064 字符串大小写转换 82 实例...

    PHP 面向对象技术(全面讲解).txt

    上面已经介绍过了,面向对象程序的单位就是对象,但对象又是通过类的实例化出来的,所以 我们首先要做的就是如何来声明类,做出来一个类很容易,只要掌握基本的程序语法定义规则就可 以做的出来,那么难点在那里呢?...

    CLR.via.C#.(中文第3版)(自制详细书签)Part1

    8.1 实例构造器和类(引用类型) 8.2 实例构造器和结构(值类型) 8.3 类型构造器 8.3.1 类型构造器的性能 8.4 操作符重载方法 8.4.1 操作符和编程语言互操作性 8.5 转换操作符方法 8.6 扩展方法 8.6.1 规则和...

    CLR.via.C#.(中文第3版)(自制详细书签)

    8.1 实例构造器和类(引用类型) 8.2 实例构造器和结构(值类型) 8.3 类型构造器 8.3.1 类型构造器的性能 8.4 操作符重载方法 8.4.1 操作符和编程语言互操作性 8.5 转换操作符方法 8.6 扩展方法 8.6.1 规则和...

    CLR.via.C#.(中文第3版)(自制详细书签)Part3

    8.1 实例构造器和类(引用类型) 8.2 实例构造器和结构(值类型) 8.3 类型构造器 8.3.1 类型构造器的性能 8.4 操作符重载方法 8.4.1 操作符和编程语言互操作性 8.5 转换操作符方法 8.6 扩展方法 8.6.1 规则和...

    CLR.via.C#.(中文第3版)(自制详细书签)Part2

    8.1 实例构造器和类(引用类型) 8.2 实例构造器和结构(值类型) 8.3 类型构造器 8.3.1 类型构造器的性能 8.4 操作符重载方法 8.4.1 操作符和编程语言互操作性 8.5 转换操作符方法 8.6 扩展方法 8.6.1 规则和...

    【05-面向对象(下)】

    把基本数据类型变量包装类实例是通过对应包装类的构造器来实现的,不仅如此,8个包装类中除了 Character之外,还可以通过传入一个字符串参数来构建包装类对象。 •如果希望获得包装类对象中包装的基本类型...

    C++ Primer第四版【中文高清扫描版】.pdf

    对于中高级程序员,本书也是不可或缺的参考书。本书的前言阐述了 第4版和前一版的不同之处。 【目录信息】 第1章 快速入门 1 1.1 编写简单的C++程序 2 1.2 初窥输入/输出 5 1.2.1 标准输入与输出对象 5 1.2.2 一个...

    Java 语言基础 —— 非常符合中国人习惯的Java基础教程手册

    而对于对象所在的实际的内存地址是不可操作的,这就保证了安全性。 1.8.4 对象的引用 对象的使用包括引用对象的成员变量和方法,通过运算符·可以实现对变量的访问和方法的调 用,变量和方法可以通过设定一定的...

    MFC的程序框架剖析

    如CTestApp,它实例化theApp全局对象)来标识的 9、基类构造函数中this指针的指向问题 在构造子类对象时,会自动调用父类的构造函数,此时在父类的构造函数中的this指针所指向的是子类对象地址 10、AfxWinMain函数 ...

    Python核心编程(第二版).pdf (压缩包分2部分,第二部分)

     第4章 python对象   4.1 python 对象   4.2 标准类型   4.3 其他内建类型   4.3.1 类型对象和type类型对象   4.3.2 none--python的null对象   4.4 内部类型   4.4.1 代码对象   4.4.2 帧...

    Python核心编程(第二版).pdf (压缩包分2部分,第一部分)

     第4章 python对象   4.1 python 对象   4.2 标准类型   4.3 其他内建类型   4.3.1 类型对象和type类型对象   4.3.2 none--python的null对象   4.4 内部类型   4.4.1 代码对象   4.4.2 帧...

    day021-反射和注解笔记和代码.rar

    1. CONSTRUCTOR:可以在构造器上使用注解 2. FIELD:可以在字段上使用注解 3. LOCAL_VARIABLE:可以在局部变量上使用注解 4. METHOD:可以在普通方法上使用注解 5. PACKAGE:可以...

    [JavaScript.DOM高级程序设计](加)桑贝斯.扫描版.part3.rar

     第4章 响应用户操作和事件   4.1 DOM2级事件   4.2 事件的类型   4.2.1 对象事件   4.2.2 鼠标移动事件   4.2.3 鼠标单击事件   4.2.4 键盘事件   4.2.5 表单相关的事件   4.2.6 针对W3C...

    [JavaScript.DOM高级程序设计](加)桑贝斯.扫描版.part2.rar

     第4章 响应用户操作和事件   4.1 DOM2级事件   4.2 事件的类型   4.2.1 对象事件   4.2.2 鼠标移动事件   4.2.3 鼠标单击事件   4.2.4 键盘事件   4.2.5 表单相关的事件   4.2.6 针对W3C...

Global site tag (gtag.js) - Google Analytics