你偶尔可能会想要写一个只有一组静态方法的和静态字段的类。这样的类有一个坏名气,因为许多人会滥用这些类而导致不去思考面向对象的思维。但是这些只有静态方法和字段的类仍然有他们的用处!他们可以被使用作为一组与原始值和数组相关的方法,java.lang.Math和java.util.Arrays就是按照这样的方式。他们可能习惯地被当做一组静态方法或者工厂使用。而有的类则是为了包含一组实现了一些接口的对象,Collections就是这样做的。(在java8之后,你可以放一些法在你想要修改的接口中),最后,这样的类可以被用来组件一组方法在一个final类中,因为你不想把他们放在一个子类中。
这样一个工具类被设计来不可实例化:因为一个实例将会没有任何意义。由于没有明确的构造器,所以编译器将会提供一个公共的默认无参构造器。对于使用者来说,这个构造器很那和其他构造器分辨,所以很容易看见一不小心就使用公共的api来实例化了一个不应该被实例化的类。
想要让一个类抽象来使一个类不可实例化是不行的!因为这个类能够被继承同时它不能被实例化,所以,他就会给使用者一个错误的导向,让使用者误以为这样设计是需要继承这样的一个类!不过,这里有一个简单的语义可以确保不可实例化,一个类可以使用仅包含一个私有构造器让他不可实例化:
// Noninstantiable utility class
public class UtilityClass {
// Suppress default constructor for noninstantiability
private UtilityClass() {
throw new AssertionError();
}
... // Remainder omitted
}
通过这个明确的私有构造器,不可能在类之外来创建一个对象。这个AssertionError不是强制需要的,但是他可以提供一些保障防止一些偶然的事故都出现的实例化(比如反射?),他可以保证一个类在无论什么场景都不能被实例化!这个方案更加直观因为这个构造器被明显地提供了以至于他不能被调用。
这样做也有一个副作用,这个方案同样让一个类不能被继承!所有的构造器都必须明确地或者隐式的调用父类的构造器,一个私有化构造器的父类的构造器永远不可能被子类调用。