偶尔情况下,你会编写只包含静态方法和静态域的类。这种类的名声不太好,因为有些人滥用他们来避免面向对象编程,不过这种类确实有他们的用处。
- 我们可以照java.lang.Math或java.util.Arrays的样子,用这种类将基本类型或数组上相关的方法组织起来;
public class Arrays {
public static void fill(long[] a, long val) {
...
}
}
- 还可以照jva.util.Collections的样子,将实现了特定接口的对象中的静态方法(包括静态工厂方法)组织起来;
public class Collections {
public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal) {
...
}
}
- 最后,这种类可以用来将final类中的方法组织起来,以取代扩展该final类。
这种工具类设计出来并不是为了实例化它,工具类的实例是无意义的。然而,如果不显式地编写构造函数,编译器则会提供一个公共的无参数的默认构造方法。对用户来说,这种构造方法和其他构造函数没有任何区别。我们经常能在已发行的API中看到这种不经意的可实例化的类。
企图通过将类定义为抽象类来强制该类不可实例化,是不可行的。因为类可被子类化,而子类可以实例化。此外,这会误导用户一位这个类是设计来继承的(Item17)。然而,一种简单的习惯用法即可确保类不可实例化。只有当类中没有显式的构造函数,编译器才会生成默认构造函数,所以,只要类中包含私有构造函数即可保证不可实例化:
// Noninstantiable utility class
public class UtilityClass{
// Suppress default constructor for noninstantiability
private UtilityClass(){
throw new AssertionError();
}
}
由于显式的构造函数是私有的,所以在类的外部不可访问该方法。
AssertionError并不是必须的,不过它确保了该方法不会再类内部被意外调用,它确保了在任何情况下该类都不会被实例化。这种习惯用法有点违背直觉,因为明明已提供了构造函数,但却不能被调用。所以,聪明的做法是增加一条注释,如上例所示。
这种习惯用法的副作用是类不能被子类化了。子类的所有构造函数必须首先隐式或显式地调用父类构造函数,而在这种用法下,子类就没有可访问的父类构造函数可调用了。
分享到:
相关推荐
4. **强化不可实例化的能力**:对于工具类或只包含静态方法的类,通过使构造器私有,可以防止其被实例化。 5. **依赖注入**:优于硬编码资源连接,依赖注入可以提高代码的可测试性和灵活性。 6. **避免创建不必要的...
通过私有构造器强化不可实例化的能力,可以防止工具类被实例化。 Builder 模式 Builder 模式是一种构建对象的方法,不直接生成想要的对象,而是利用必要参数调用构造器(或者静态工厂)得到一个 builder 对象,...
- 不可实例化:当类设计为工具类,不希望有实例存在时,可以使用私有构造器来防止外部实例化。 - 不可变值类:使用预先构建的实例或构造时缓存实例,确保不会创建重复对象。 4. 基于接口的框架:通过接口提供静态...
- Item4:如果一个类不应当被实例化,使用私有构造子并配合`final`关键字使其成为不可初始化的常量类。 2. **避免产生不必要的对象** - Item5:尽量重用对象,特别是对于不可变对象,如字符串,它们在常量池中会...
《Effective Java》是一本经典Java编程指南,作者是Joshua Bloch,这本书深入探讨了如何编写高质量、高效、可维护的Java代码。以下是对压缩包中各章节主要知识点的详细阐述: 1. **第2章 创建和销毁对象** - 单例...
4. **构造器**:书中阐述了如何设计和使用构造器来创建对象,强调了单参数构造器和工厂方法的优缺点,以及如何利用Builder模式来构建复杂对象。 5. **异常处理**:异常处理是Java编程中的一个重要方面,Bloch建议...
只有当类不包含显式构造方法时,才会生成一个默认构造方法,因此可以通过包含一个私有构造方法来实现类的非实例化:// 不可实例化的程序类// 禁止默认构造函数以实现
* 可以使得参数设置变得清晰易懂:构造器模式可以使用fluent API的方式来构造对象,提高代码的可读性。 * 可以让代码具有很好的可读性和可维护性:构造器模式可以使得代码更加简洁和易于理解。 然而,构造器模式也...
4. **尽可能使用不可变对象( Prefer Immutable Objects)**:不可变对象一旦创建就无法改变其状态,这有助于线程安全和减少错误。例如,String类就是不可变的。通过使对象不可变,可以简化并发编程,并防止意外修改...
目录:一、创建和销毁对象 (1 ~ 7)二、对于所有对象都通用的方法 (8 ~ 12)三、类和接口 (13 ~ 22)四、泛型 (23 ~ 29)五、枚举和注解 (30 ~ 37)六、方法 (38 ~ 44)七、通用程序设计 (45 ~ 56)八、异常 ...
4. **构造函数与析构函数**:C++中的构造函数和析构函数是对象生命周期的关键部分。书中会讲解如何利用它们进行初始化和清理资源,以及何时使用构造函数初始化列表。 5. **运算符重载**:C++允许用户为自定义类型...
根据提供的标题和描述,我们将探讨三个关键知识点:最小化类和成员的可访问性、使用访问方法而非公有域以及使可变性最小化,通过创建不可变类。 首先,让我们深入理解"使类和成员的可访问性最小化"这一原则。在面向...
Builder 模式是一种创建复杂对象的模式,它可以帮助我们解决字段私有、不可变、有必填及选填字段的问题。在 Builder 模式中,我们可以使用静态内部类 Builder 来创建对象。 例如,在 Fruit 类中,我们可以使用 ...
12. **统一初始化**:C++11的统一初始化语法允许使用花括号{}来初始化任何类型的对象,提高了代码的简洁性和一致性。 13. **`std::unordered_map`和`std::unordered_set`**:哈希表实现的关联容器,提供了更快的...
14. **`std::make_unique`和`std::make_shared`**:理解这两个工厂函数优于直接调用构造函数创建智能指针的原因。 15. **成员初始化列表**:在构造函数中使用成员初始化列表以优化对象初始化,防止不必要的拷贝和...