天天看点

Java类的域初始化_Java域的初始化

域的初始化

现在回忆一下我们在《Java基础教程(5)--变量》一文中学习过的有关域的默认值的内容。在声明域时,如果不对它进行显式的初始化,编译器将赋予它一个默认值。如果是基本数据类型的域,根据它的类型,它的默认值将会是:

Java类的域初始化_Java域的初始化

如果是引用类型的域,它的默认值将会是null。

除了这种默认的初始化行为,是否还有其他方式可以在使用对象前对域进行初始化呢?答案是肯定的。下面我们将分别介绍非静态域和静态域初始化行为。

1.初始化非静态域

(1)默认初始化

正如上文所说,在声明域时,如果不对它进行赋值,编译器将赋予它一个默认值。例如:

public class Bag {

public int capacity;

}

在创建完Bag类的对象以后,capacity域的值将会是0。

(2)显式初始化

也可以在声明域的同时给它提供一个初始值,就像下面这样:

public class Bag {

public int capacity = 10;

}

(3)在构造方法中进行初始化

构造方法也可以对域进行初始化:

public class Bag {

public int capacity;

public Bag(int capacity) {

this.capacity = capacity;

}

}

(4)非静态代码块

下面定义了一个非静态代码块对域进行初始化:

public class Bag {

public int capacity;

{

capacity = 10;

}

}

与非静态代码块对应的是静态代码块,马上会在下文中介绍。编译器会将初始化块拷贝到每个构造方法最前面的位置,因此,这种方法可以用来在多个构造方法中共享代码块。一个类中可以定义多个代码块,它们可以出现在类体中的任何位置,它们的执行顺序与源代码中的定义顺序相同。

(5)调用方法进行初始化

下面调用了一个方法对域进行初始化:

public class Bag {

public int capacity;

private int initializeCapacity() {

return 10;

}

}

当然实际编写代码过程中这个方法的逻辑肯定没有这么简单,这里只是为了举个例子。如果子类想要重用这个初始化方法可以将方法的访问权限设置为protected,但是同时应该使用final修饰符来禁止子类重写(有关重写的内容会在后续文章中进行介绍)这个方法(PS:Java Tutorial里说在实例初始化期间调用非final方法可能会导致问题,我暂时没想到会出现什么问题,如果有知道的大神还请点拨一二,下面是原文的截图)。

Java类的域初始化_Java域的初始化

在了解完这几种初始化的方式以后,我们就可以在编写代码时根据它们的性质灵活选择。但是如果这几种初始化方式同时出现的话,它们的顺序又是怎么样呢?由于默认初始化和显示初始化都是在声明域的同时完成的,这两种方式只能同时出现一种;又由于使用方法对域进行初始化的方式只是一种获取值的形式,并不属于初始化时机的讨论范围之内,它在显式初始化、构造方法和代码块中都可以使用,所以实际上可以将这五种方式总结为三种。它们的顺序如下(大于号代表左边的顺序早于右边的):

默认初始化、显示初始化>非静态代码块>构造方法

2.初始化静态域

与非静态域相比,由于静态域的初始化与类是否实例化无关,所以不讨论在构造方法中对静态域赋值的方式(不代表不可以这么做,但是不建议将静态域与类的实例之间建立任何联系)。其余四种形式都有与之对应的初始化行为,默认初始化与显式初始化较为简单,这里不再赘述。

与非静态域的非静态代码块对应的是静态代码块,一个类可以有任意数量的静态代码块,它们可以出现在类中的任何位置,编译器保证按照它们在源代码中出现的顺序调用静态代码块。

也可以使用静态方法对静态域赋值,就像非静态域那样。

静态域的初始化顺序如下:

默认初始化、显示初始化>静态代码块