4.1 用构造器自动初始化
4.1 用构造器自动初始化
对于方法的创建,可将其想象成为自己写的每个类都调用一次 initialize()。这个名字提醒我们在使用对象之前,应首先进行这样的调用。但不幸的是,这也意味着用户必须记住调用方法。在 Java 中,由于提供了名为“构造器”的一种特殊方法,所以类的设计者可担保每个对象都会得到正确的初始化。若某个类有一个构造器,那么在创建对象时,Java 会自动调用那个构造器——甚至在用户毫不知觉的情况下。所以说这是可以担保的!
接着的一个问题是如何命名这个方法。存在两方面的问题。第一个是我们使用的任何名字都可能与打算为某个类成员使用的名字冲突。第二是由于编译器的责任是调用构造器,所以它必须知道要调用是哪个方法。C++采取的方案看来是最简单的,且更有逻辑性,所以也在 Java 里得到了应用:构造器的名字与类名相同。这样一来,可保证象这样的一个方法会在初始化期间自动调用。
下面是带有构造器的一个简单的类(若执行这个程序有问题,请参考第 3 章的“赋值”小节)。
//: SimpleConstructor.java
// Demonstration of a simple constructor
package c04;
class Rock {
Rock() { // This is the constructor
System.out.println("Creating Rock");
}
}
public class SimpleConstructor {
public static void main(String[] args) {
for(int i = 0; i < 10; i++)
new Rock();
}
} ///:~
现在,一旦创建一个对象:
new Rock();
就会分配相应的存储空间,并调用构造器。这样可保证在我们经手之前,对象得到正确的初始化。 请注意所有方法首字母小写的编码规则并不适用于构造器。这是由于构造器的名字必须与类名完全相同! 和其他任何方法一样,构造器也能使用自变量,以便我们指定对象的具体创建方式。可非常方便地改动上述例子,以便构造器使用自己的自变量。如下所示:
class Rock {
Rock(int i) {
System.out.println(
"Creating Rock number " + i);
}
}
public class SimpleConstructor {
public static void main(String[] args) {
for(int i = 0; i < 10; i++)
new Rock(i);
}
}
利用构造器的自变量,我们可为一个对象的初始化设定相应的参数。举个例子来说,假设类 Tree 有一个构造器,它用一个整数自变量标记树的高度,那么就可以象下面这样创建一个 Tree 对象:
tree t = new Tree(12); // 12英尺高的树
若 Tree(int)是我们唯一的构造器,那么编译器不会允许我们以其他任何方式创建一个 Tree 对象。
构造器有助于消除大量涉及类的问题,并使代码更易阅读。例如在前述的代码段中,我们并未看到对 initialize()方法的明确调用——那些方法在概念上独立于定义内容。在 Java 中,定义和初始化属于统一的概念——两者缺一不可。 构造器属于一种较特殊的方法类型,因为它没有返回值。这与 void 返回值存在着明显的区别。对于 void 返回值,尽管方法本身不会自动返回什么,但仍然可以让它返回另一些东西。构造器则不同,它不仅什么也不会自动返回,而且根本不能有任何选择。若存在一个返回值,而且假设我们可以自行选择返回内容,那么编译器多少要知道如何对那个返回值作什么样的处理。