对于方法的创建,可将其想象成为自己写的每个类都调用一次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) {
96
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 返
回值,尽管方法本身不会自动返回什么,但仍然可以让它返回另一些东西。构建器则不同,它不仅什么也不
会自动返回,而且根本不能有任何选择。若存在一个返回值,而且假设我们可以自行选择返回内容,那么编
译器多少要知道如何对那个返回值作什么样的处理。
之前,应首先进行这样的调用。但不幸的是,这也意味着用户必须记住调用方法。在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) {
96
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 返
回值,尽管方法本身不会自动返回什么,但仍然可以让它返回另一些东西。构建器则不同,它不仅什么也不
会自动返回,而且根本不能有任何选择。若存在一个返回值,而且假设我们可以自行选择返回内容,那么编
译器多少要知道如何对那个返回值作什么样的处理。