类,该类中的非静态代码块就会被执行一次。
Java的初始化类、变量、程序块加载探讨(4)
时间:2011-03-20 zhangjunhd
6.数组初始化
注意区分基本类型数据与类数据的初始化。看以下代码:
int[] a;
a = new int[rand.nextInt(20)];
与
Integer[] a = new Integer[rand.nextInt(20)];
for(int i = 0; i < a.length; i++) {
a[i] = new Integer(rand.nextInt(500));
}
对于类数据类型的初始化,每个数组子成员都要重新new一下。
7.涉及继承关系的初始化
当创建一个导出类的对象时,该对象包含了一个基类的子对象。看下面代码:
class Art {
Art() {
System.out.println("Art constructor");
}
}
class Drawing extends Art {
Drawing() {
System.out.println("Drawing constructor");
}
}
public class Cartoon extends Drawing {
public Cartoon() {
System.out.println("Cartoon constructor");
}
public static void main(String[] args) {
new Cartoon();
}
}
结果:
Art constructor
Drawing constructor
Cartoon constructor
可以发现,构建过程是从基类“向外”扩散的,所以基类在导出类构造器可以访问它之前,就已经完成了初始化。
如果类没有缺省的参数,或者想调用一个带参数的基类构造器,就必须用关键字super显示地调用基类构造器的语句,并且配以适当的参数列表。看下面代码:
class Game {
Game(int i) {
System.out.println("Game constructor");
}
}
class BoardGame extends Game {
BoardGame(int i) {
super(i);
System.out.println("BoardGame constructor");
}
}
public class Chess extends BoardGame {
Chess() {
super(11);
System.out.println("Chess constructor");
}
public static void main(String[] args) {
new Chess();
}
}
结果:
Game constructor
BoardGame constructor
Chess constructor
如果不在BoardGame()中调用基类构造器,编译器将无法找到符合Game()形式的构造器。而且,调用基类构造器必须是你在导出类构造器中要做的第一件事。
Java的初始化类、变量、程序块加载探讨(5)
时间:2011-03-20 zhangjunhd
8.构造器与多态
8.1构造器的调用顺序
基类的构造器总是在导出类的构造过程中被调用的,而且按照继承层次逐渐向上链接,以使每个基类的构造器都能得到调用。这样做是有意义的,因为构造器具有一项特殊的任务:检查对象是否被正确地构造。导出类只能访问它自己的成员,不能访问基类中的成员(基类成员通常是private类型)。只有基类的构造器才具有恰当的知识和权限来对自己的元素进行初始化。因此,必须令所有构造器都得到调用,否则就不可能正确构造完整对象。这正是编译器为什么要强制每个导出类部分都必须调用构造器的原因。
8.2构造器内部的多态方法的行为
看下面代码:
abstract class Glyph {
abstract void draw();
Glyph() {
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() after draw()");
}
}
class RoundGlyph extends Glyph {
private int radius = 1;
RoundGlyph(int r) {
radius = r;
System.out.println("RoundGlyph.RoundGlyph(),radius=" + radius);
}
void draw() {
System.out.println("RoundGlyph.draw(),radius=" + radiu
|