在看到Thinking in java 第四章时初始化相关问题的时候,我们不由地把注意力移到构造器上。这里做个简单的总结,便于高手指正以及自己温故。
首先构造器是要构造一个东西{构造对象(实例)}并对其初始化。之所以很多程序中没有看到它,是因为在java程序中如果你没定义任何构造器,则编译器会自动给你加上默认构造器(不带任何参数,也没有“方法体”)。倘若自己定义了构造方法,编译器将不再自动添加。构造器是可以提供很多方法,但与构造方法又有所不同。如Robert Nielsen 所说,这关系就好似澳大利亚的鸭嘴兽是一种哺育动物。(要理解鸭嘴兽,那么先必须理解它和其他哺育动物的区别。)
其次构造器有几点简单的要求:
a,构造器需采用与类名相同的名称(大小写也要一致);
b,构造器没有返回值(也无需添加void);
c, 构造器修饰符仅有public,private及protected三个;
d,构造器与构造方法存在不同,如构造方法不仅要给对象实例变量赋值,并和new一起创建对象。
e,父类中的构造器不能被继承,父类中的方法可以继承。
f,同一类中的构造器可以重载。
g,子类与父类构造器编译时常出错的关键如下:
例一:
class A {
public A() {
System.out.println("A");
}
}
class B extends A{
public B(String str) {
System.out.println("B");
}
}
class C extends B{
public C(String str) {super(str);System.out.println("C String");
}
public C(int n) {System.out.println("C int");super("" + n);
}
}
说明:
编译错误,调用父类的构造器语句应该为类构造器中的第一个语句。
修改为:public C(int n) {super("" + n);System.out.println("C int");}
使用:C c = new C(10); //输出:A B C
例二:
class TestSuper{
TestSuper(int i){} //指定了一个有参数的构造器,系统将不再为该类提供默认构造器
}
class TestSub extends TestSuper{ //在这里子类未定义构造器,系统将会提供默认构造器
TestSuper(){ super();}
}
public class TestAll{
public static void main(String args[]){
new TestSub();
}
}
不能编译成功,如果我们在eclipse这样写的话,就会有错误提示。
解决方法1:
在子类TestSub中添加无参数构造函数:
public TestSub() {
super(0);
//显式调用父类的带参数的构造器
}
解决方法2:
在TestSuper类添加无参数构造函数TestSuper(){} //显式指定父类的无参构造器
注意:1.使用super调用构造器的语句必须是子类构造器的第一条语句
构造子类时,如果子类没有定义构造函数,就调用父类的构造函数。由于子类(TestSub)的构造器不能访问超类(TestSuper)的私有域(private成员),所以必须利用子类TestSub的构造器对超类的私有域进行初始化,通过super实现对超类(TestSuper)构造器的调用。
期间,我们看到TestSuper类提供了一个简单的构造器:TestSuper(int i){}
2.如果在编写一个类时没有编写构造器,系统就会提供一个默认构造器,同时这个默认构造起将所有的实例域设置为默认值,例如:实例域中的数值型数据设置为0、布尔型数据设置为false、所有对象变量将设置为null。
3.类的构造器可以实现对实例的初始化,这是在有参数的情况下。例如:在定义一个Students类的时候:
class Tree{
Tree(int i){
System.out.println("Tree is "+i +"-foot");
}
}
public class Parameters {
public static void main(String[] args) {
for(int i=1;i<10;i++)
new Tree(i);
}
}//我们可以直接在结果中可以看到对i赋值了。