有这样一个问题:
例如下面这样的代码块,通过实例化导出类的构造器方法,最后结果是什么?
class Example{
{
System.out.println("super Example non-static");
}
public Example(){
System.out.println("super Example constructor");
}
static {
System.out.println("super B static");
}
}
public class ConstructorExample extends Example{
static {
System.out.println("this static");
}
{
System.out.println("this non-static");
}
public ConstructorExample(){
System.out.println("this constructor");
}
public static void main(String[] args) {
ConstructorExample example = new ConstructorExample();
}
}
这段代码,对于子类跟其父类来说,都有构造器方法、静态块和非静态块,将程序运行之后,可得结果如下:
由此,结论:
首先,每个类的初始化顺序为静态变量、静态块、实例变量、实例块、构造器。
由此,对于某个基类导出的新类
1)先初始化父类的静态块、接下来是子类的静态块。
静态关键字表示只能被初始化一次,只占用一份内存。
2)对父类的非静态块和构造器依次进行初始化
3)初始化子类的非静态块,构造器
4)静态块与静态块之间、非静态块与非静态块之间的顺序则是按照先后顺序进行初始化(经检测无误,这不是写这篇博客的目的,未在代码中体现)
5)静态块只被初始化一次,而非静态块和构造器方法会随着 new 关键字被重新初始化一次,顺序如 2)、3)
如下:
class Example{
{
System.out.println("super Example non-static");
}
public Example(){
System.out.println("super Example constructor");
}
static {
System.out.println("super B static");
}
}
public class ConstructorExample extends Example{
static {
System.out.println("this static");
}
{
System.out.println("this non-static");
}
public ConstructorExample(){
System.out.println("this constructor");
}
public static void main(String[] args) {
new ConstructorExample();
new ConstructorExample();
}
}
其中静态块只被初始化一次,非静态块和构造器方法随着 new 关键字的出现被初始化两次。
原因:
子类的构造器中默认含有父类的构造器
public ConstructorExample(){
System.out.println("this constructor");
}
//等价于
public ConstructorExample(){
super();
System.out.println("this constructor");
}
所以对子类初始化的时候会对父类进行初始化,如果不使用默认的构造器,调用子类构造器时,可以调用我们自己定义的构造器
class Example{
{
System.out.println("super Example non-static");
}
public Example(int a){
System.out.println("super Example has a parameter");
}
public Example(){
System.out.println("super Example constructor");
}
static {
System.out.println();
}
static {
System.out.println("super B static");
}
}
public class ConstructorExample extends Example{
static {
System.out.println("this static");
}
{
System.out.println("this non-static");
}
public ConstructorExample(){
super(3);
System.out.println("this constructor");
}
public static void main(String[] args) {
new ConstructorExample();
}
}
即使父类中有无参的构造器,而我们在子类的构造器中调用了有参的父类构造器,自然只能初始化父类有参的构造器。