可以假想为编写的每个类都定义一个 initialize( )方法。此名称提醒你在使用其对象之前,应
首先调用 initialize( )。然而,这同时意味着用户必须记得自己去调用此方法。在 Java 中,通
过提供“构造器”这种特殊方法,类的设计者可确保每个对象都会得到初始化。当对象被创
建时,如果其类具有构造器,Java 就会在用户有能力操作对象之前自动调用相应的构造器,
所以初始化动作得以确保。
接下来的问题就是如何命名这个方法。有两个问题:第一,你取的任何名字都可能与类的某
个成员名称相冲突;第二,调用构造器是编译器的责任,所以必须让编译器知道应该调用哪
个方法。C++语言中采用的方案看来最简单且更符合逻辑,所以在 Java 中也得到了应用:
即构造器采用与类相同的名称。考虑到在初始化期间要自动调用构造器,这种作法就顺理成
章了。
以下就是一个带有构造器的简单类:
//: c04:SimpleConstructor.java
// Demonstration of a simple constructor.
import com.bruceeckel.simpletest.*;
class Rock {
Rock() { // This is the constructor
System.out.println("Creating Rock");
}
}
public class SimpleConstructor {
static Test monitor = new Test();
public static void main(String[] args) {
for(int i = 0; i < 10; i++)
new Rock();
monitor.expect(new String[] {
"Creating Rock",
"Creating Rock",
"Creating Rock",
"Creating Rock",
"Creating Rock",
"Creating Rock",
"Creating Rock",
"Creating Rock",
"Creating Rock",
"Creating Rock"
});
}
} ///:~
现在,在创建对象时:
new Rock();
将会为对象分配存储空间,并调用相应的构造器。这就确保了在你能操作对象之前,它已经
被恰当地初始化了。
请注意,由于构造器的名称必须与类名完全相同,所以“每个方法首字母小写”的编码风格
并不适用于构造器。
和其他方法一样,构造器也能带有形式参数,以便指定对象的具体创建方式。对上述例子稍
加修改,即可使构造器接受一个参数:
//: c04:SimpleConstructor2.java
// Constructors can have arguments.
import com.bruceeckel.simpletest.*;
class Rock2 {
Rock2(int i) {
System.out.println("Creating Rock number " + i);
}
}
public class SimpleConstructor2 {
static Test monitor = new Test();
public static void main(String[] args) {
for(int i = 0; i < 10; i++)
new Rock2(i);
monitor.expect(new String[] {
"Creating Rock number 0",
"Creating Rock number 1",
"Creating Rock number 2",
"Creating Rock number 3",
"Creating Rock number 4",
"Creating Rock number 5",
"Creating Rock number 6",
"Creating Rock number 7",
"Creating Rock number 8",
"Creating Rock number 9"
});
}
} ///:~
有了构造器形式参数,你就可以在初始化对象时提供实际参数。假设类 Tree 有一个构造器,
它接受一个整型变量来表示树的高度,你就可以这样创建一个 Tree 对象:
Tree t = new Tree(12); // 12-foot tree
如果 Tree(int)是 Tree 类中唯一的构造器,那么编译器将不会允许你以其他任何方式创建 Tree
对象。
构造器有助于减少错误,并使代码更易于阅读。从概念上讲,“初始化”与“创建”是彼此
独立的,然而在上面的代码中,你却找不到对类似 initialize( )方法的直接调用。在 Java 中,
“初始化”和“创建”被捆绑在一起,两者不能分离。
构造器比较特殊,因为它没有返回值。这与返回值为空(void)明显不同。对于空返回值,
尽管方法本身不会自动返回什么,但你仍可选择让它返回别的东西。构造器则不会返回任何
东西,你别无选择(new 表达式确实返回了对新建对象的引用,但构造器本身并没有任何
返回值)。假如构造器具有返回值,并且允许你自行选择返回类型,那么势必得让编译器知
首先调用 initialize( )。然而,这同时意味着用户必须记得自己去调用此方法。在 Java 中,通
过提供“构造器”这种特殊方法,类的设计者可确保每个对象都会得到初始化。当对象被创
建时,如果其类具有构造器,Java 就会在用户有能力操作对象之前自动调用相应的构造器,
所以初始化动作得以确保。
接下来的问题就是如何命名这个方法。有两个问题:第一,你取的任何名字都可能与类的某
个成员名称相冲突;第二,调用构造器是编译器的责任,所以必须让编译器知道应该调用哪
个方法。C++语言中采用的方案看来最简单且更符合逻辑,所以在 Java 中也得到了应用:
即构造器采用与类相同的名称。考虑到在初始化期间要自动调用构造器,这种作法就顺理成
章了。
以下就是一个带有构造器的简单类:
//: c04:SimpleConstructor.java
// Demonstration of a simple constructor.
import com.bruceeckel.simpletest.*;
class Rock {
Rock() { // This is the constructor
System.out.println("Creating Rock");
}
}
public class SimpleConstructor {
static Test monitor = new Test();
public static void main(String[] args) {
for(int i = 0; i < 10; i++)
new Rock();
monitor.expect(new String[] {
"Creating Rock",
"Creating Rock",
"Creating Rock",
"Creating Rock",
"Creating Rock",
"Creating Rock",
"Creating Rock",
"Creating Rock",
"Creating Rock",
"Creating Rock"
});
}
} ///:~
现在,在创建对象时:
new Rock();
将会为对象分配存储空间,并调用相应的构造器。这就确保了在你能操作对象之前,它已经
被恰当地初始化了。
请注意,由于构造器的名称必须与类名完全相同,所以“每个方法首字母小写”的编码风格
并不适用于构造器。
和其他方法一样,构造器也能带有形式参数,以便指定对象的具体创建方式。对上述例子稍
加修改,即可使构造器接受一个参数:
//: c04:SimpleConstructor2.java
// Constructors can have arguments.
import com.bruceeckel.simpletest.*;
class Rock2 {
Rock2(int i) {
System.out.println("Creating Rock number " + i);
}
}
public class SimpleConstructor2 {
static Test monitor = new Test();
public static void main(String[] args) {
for(int i = 0; i < 10; i++)
new Rock2(i);
monitor.expect(new String[] {
"Creating Rock number 0",
"Creating Rock number 1",
"Creating Rock number 2",
"Creating Rock number 3",
"Creating Rock number 4",
"Creating Rock number 5",
"Creating Rock number 6",
"Creating Rock number 7",
"Creating Rock number 8",
"Creating Rock number 9"
});
}
} ///:~
有了构造器形式参数,你就可以在初始化对象时提供实际参数。假设类 Tree 有一个构造器,
它接受一个整型变量来表示树的高度,你就可以这样创建一个 Tree 对象:
Tree t = new Tree(12); // 12-foot tree
如果 Tree(int)是 Tree 类中唯一的构造器,那么编译器将不会允许你以其他任何方式创建 Tree
对象。
构造器有助于减少错误,并使代码更易于阅读。从概念上讲,“初始化”与“创建”是彼此
独立的,然而在上面的代码中,你却找不到对类似 initialize( )方法的直接调用。在 Java 中,
“初始化”和“创建”被捆绑在一起,两者不能分离。
构造器比较特殊,因为它没有返回值。这与返回值为空(void)明显不同。对于空返回值,
尽管方法本身不会自动返回什么,但你仍可选择让它返回别的东西。构造器则不会返回任何
东西,你别无选择(new 表达式确实返回了对新建对象的引用,但构造器本身并没有任何
返回值)。假如构造器具有返回值,并且允许你自行选择返回类型,那么势必得让编译器知
道该如何处理此返回值。