`
TonyLian
  • 浏览: 401501 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

【第3条】通过私有构造函数强化不可实例化的能力

阅读更多

    有时候你可能编写出只包含静态方法和静态域的类。这样的类有一些很不好的名声,因为有些人在面向对象的语言中滥用这样的类来编写过程化的程序。

 

    对原文这句话的理解,我有着深刻的印象,有很多从VB6工程转过来做Java或C#(包括VB.Net)的程序员,在抱怨:还是VB6好用,各种方法简单明了,像什么  left()  trim()  split()  cstr()  replace() 等方法多简单好用。到了这些面向对象的语言里,还非得 Class.function() 的使用。

 

    值得庆幸的是,他们只发现原来VB6的那些库函数用起来变得要在前面加上一个类的名字。原来自己写的那些函数(主要是private的)依然还是已类中函数出现的,有朝一日,如果有人发现原来的public函数(模块中的)不好使了,要为此写个类,然后通过 类名.方法名 来调用,那么多半就犯了原文中所提到的错误了——静态方法滥用。

 

    更有甚者,尚不知静态与非静态的区别, 直接这样写:  new Samething().doSamething();

 

     有些跑题了,回到不可实例化的能力上来。工具类(util)就是一类不该被实例化类的代表。它们只是提供一些实用功能,实例化之是毫无意义的。例如刚刚提到的一些 String 相关的功能性函数:如 replace

String已经提供了一个replace方法,它是个非静态的方法,通常的用法是 String s2 = s1.replace("x", "y");

我们假设String所提供的replace只能将s1中的首个"x"替换为"y",为了能够将s1中的所有"x"都替换为"y",我们可以写这样一个工具类

public StringUtil{
     public static String replace(String str, String pattern, String repl){
         String rtn= str;
         while (rtn.instring(pattern)>=0){
              rtn = rtn.replace(pattern,repl);
         }
         return rtn;
    }
}

 

然后这样使用: String s2 = StringUtil.replace(s1,"x","y");

 

    这个例子可能并不太好(因为String提供的replace本来就可以替换全部的,其实这个例子是源于Flex的AS3语言的,AS3中的String所提供的replace方法就是仅能替换首个相匹配项的)

 

    似乎又跑题了,跑到了什么是“工具类”上了。还是回来说如何使一个类不可被实例化吧,其实很简单给它写一个私有的构造函数,而且保证类内部没有地方调用这个构造函数即可。

由于构造函数仅有一个私有的,所以外部是无法调用到的,而内部也做的不调用,这就保证了这个类永远也不会被实例化。

有人可能会问了,那根本就不写构造函数不是更简单?其实不然,如果根本就不写任何构造函数,编译的时候,编译器是会给这个类自动加上一个空的公有构造函数的,那么就“泄了真气”了。其实这里要写的私有构造函数仅仅是个空的就可以,因为根本不会有任何地方调用它,它在这里仅仅是充个数而已(just be here !)

 

    当然,有一个好的习惯,就是每每有这样的处理的时候,你应该在这个空的私有构造函数处写上注释,告诉后人这个空的私有构造函数的用意是禁止类被实例化用的。这一点很重要!否则后人可能会误认为你在这里犯了一个错误(误把public写成了private),并“修改”之。

 

    看完此条,我要做的第一件事(除了写这个笔记外),就是重新审查一遍我所有的util.* ,为它们都增加一个空的私有构造函数并写上注释。好了,now, do it !

 

 

【Effective Java 学习笔记】系列连载请见:http://tonylian.iteye.com/categories/64208

 

分享到:
评论

相关推荐

    C#学习笔记整理_深入剖析构造函数、析构函数

    4.私有构造函数:则无法通过该构造函数实例化该对象,可通过调用静态函数来实例化;当仅用作某些静态成员或属性的容器时,可定义私有构造函数来防止被实例化; 一般的构造函数都是实例构造函数,只要创建实例,就...

    Java中对象的生命周期 ..doc

    - 构造函数不能被声明为`static`、`final`、`synchronized`、`native`或`abstract`。 3. **默认构造函数**: - 如果一个类没有定义任何构造函数,则系统会自动提供一个无参的默认构造函数。 - 如果类中至少定义...

    C# 静态构造函数使用总结

    与实例构造函数不同,静态构造函数不接受任何参数,也不与特定对象的创建相关联。以下是关于C#静态构造函数的一些关键点: 1. **访问性**:静态构造函数没有访问修饰符。这意味着它们默认为私有,不能从类外部直接...

    2022年面向对象程序设计在线测试.docx

    2. **构造函数**:第3题提到了构造函数的调用时机。构造函数用于初始化类的对象,当对象被创建时,对应的构造函数会被自动调用。例如,`ab x;`会调用类`ab`的无参构造函数。 3. **成员函数和对象指针**:第4题中,...

    C++ 单一实例

    Singleton() {} // 私有构造函数 Singleton(const Singleton&) {} // 私有拷贝构造函数 Singleton& operator=(const Singleton&) { return *this; } // 私有赋值运算符 static Singleton* instance; // 静态...

    Effective Java第三版1

    4. **强化不可实例化的能力**:对于工具类或只包含静态方法的类,通过使构造器私有,可以防止其被实例化。 5. **依赖注入**:优于硬编码资源连接,依赖注入可以提高代码的可测试性和灵活性。 6. **避免创建不必要的...

    js中函数的理解

    3. **使用`new Function()`构造函数**: 这是一种不太常见的创建函数的方式,通过`Function`构造函数,将函数体作为字符串传递。例如: ```javascript var fun1 = new Function("a", "b", "return a + b;"); ``` 在...

    C++经典面试题 附带参考答案.docx

    当类的构造函数是私有的时,不像普通类那样实例化自己,只能通过静态成员函数来调用构造函数。 在类外可以通过友元、继承、公有成员函数来访问类的非公有成员。 抽象类是指不用来定义对象而只作为一种基本类型...

    张逸凯_171840708_高程第三次作业1

    创建此类对象时,构造函数的调用顺序是这样的:首先调用自身类的构造函数,但在构造函数体执行之前,会先调用成员对象的构造函数,按照成员对象在类定义中的顺序逐个初始化。析构函数的调用顺序则与构造函数相反,先...

    JavaScript与OOP

    - **类方法**:通过构造函数定义,可直接通过构造函数名调用。 总的来说,JavaScript的面向对象特性主要体现在其动态性、灵活性和基于原型的继承。通过巧妙地运用`apply`、`call`以及构造函数、原型链等机制,...

    c++概念问答

    3. **自身构造函数**: 最后调用自己的构造函数。 #### 十二、初始化成员列表 在某些情况下,必须使用初始化成员列表来初始化成员变量,例如: - 成员是常量成员。 - 成员是对象,且该对象没有无参构造函数。 - 成员...

    c++面试300题(华为,易思博,中软)

    14. 静态成员函数:用于访问类的静态成员,或在类的构造函数为私有时调用构造函数。 15. 访问非公有成员:通过友元函数、继承或公有成员函数。 16. 抽象类:不用于实例化,仅作为其他类继承的基础。 17. 运算符...

    实验报告第三次1

    【实验报告第三次1】主要涉及了C++编程中的类和对象相关的知识点,包括类的构造函数、静态函数、快速测试以及const关键字的应用。以下是这些知识点的详细解释: 1. **构造函数与默认参数**: - 构造函数用于初始化...

    Java学习总结(2023/03/19)

    19. 使用私有构造函数实现不可实例化的工具类。 20. 使用枚举来实现Singleton模式。 21. 避免创建不必要的对象。 22. 使用System.arraycopy()方法复制数组。 23. 对于可序列化类,明确指定serialVersionUID。 以上...

    2019011008_刘雪枫_第(4)次作业1

    例如,`Point`类有三个构造函数:一个默认构造函数初始化`x`和`y`为0,一个带参数的构造函数用于设置初始坐标,还有一个拷贝构造函数用于复制另一个`Point`对象的坐标。 - 类的析构函数以`~`符号开头,用于在对象...

    C++经典面试题库 附带参考答案.docx

    14. 静态函数:静态成员函数属于类而不属于特定对象,可用于访问静态成员,或在类构造函数私有时作为访问构造函数的入口。 15. 访问非公有成员:通过友元函数、继承或公有成员函数可以访问非公有成员。 16. 抽象类...

    C++程序设计语言 ( 第2次 ).docx

    构造函数不能声明为虚函数,析构函数可以声明为虚函数。选项B错误。 12. 重载运算符++:后缀形式的`++`运算符重载应声明为`A operator ++(int)`,选项A正确。 13. 静态成员函数:静态成员函数不能访问非静态成员,...

    c++程序设计与面向对象,第三章类和对象

    《C++程序设计与面向对象》第三章主要探讨了C++中的核心概念——类和对象。类是面向对象编程的基础,它允许我们自定义数据类型,封装数据和操作这些数据的函数,以此来构建复杂的软件系统。 3.1 类和类的定义 类的...

    java中静态与非静态的区别

    - **静态类**不可实例化。也就是说,你无法创建一个静态类的对象。这是因为它没有非静态成员或方法,也就没有实例化的必要。 - **非静态类**可以实例化,即可以通过`new`关键字创建一个该类的实例。 3. **调用...

    Python面向对象程序设计中类的定义、实例化、封装及私有变量/方法详解

    ### Python面向对象程序设计中类的定义、实例化、封装及私有变量/方法详解 #### 1. 定义类 在Python中,面向对象编程(Object-Oriented Programming, OOP)是一种重要的编程范式,它使得代码更加模块化、可重用,...

Global site tag (gtag.js) - Google Analytics