一.不考慮繼承的情況,一個類中的初始化順序是:
1.靜態變量,包括靜態代碼塊
2.普通變量,包括普通代碼塊
3.執行構造函數
舉個例子:
class Sample {
public Sample() {
System.out.println("調用Sample的默認構造函數");
}
public Sample(String s) {
System.out.println(s + ":調用Sample的含參構造函數");
}
}
public class Test {
public Test() {
System.out.println("調用Test的默認構造函數");
}
{
System.out.println("Test的非靜態代碼塊");
}
static {
System.out.println("Test的靜態代碼塊");
}
private Sample sample2 = new Sample();
private static Sample sample1 = new Sample("靜態成員sample1初始化:");
public static void main(String args[]) {
System.out.println("main函數");
new Test();
System.out.println("已經構造完Test的匿名對象");
}
}
輸出結果:
Test的靜態代碼塊
靜態成員sample1初始化::調用Sample的含參構造函數
main函數
Test的非靜態代碼塊
調用Sample的默認構造函數
調用Test的默認構造函數
已經構造完Test的匿名對象
補充:對於靜態成員和普通成員,其初始化順序只與在類中定義的順序有關,與其他因素無關
例子如下:
class Sample {
public Sample() {
System.out.println("調用Sample的默認構造函數");
}
public Sample(String s) {
System.out.println(s + ":調用Sample的含參構造函數");
}
}
public class Test {
public Test() {
System.out.println("調用Test的默認構造函數");
}
{
System.out.println("Test的非靜態代碼塊1");
}
static {
System.out.println("Test的靜態代碼塊1");
}
private Sample sample1 = new Sample("sample1初始化:");
private static Sample staticSample1 = new Sample("靜態成員staticSample1初始化:");
private static Sample StaticSample2 = new Sample("靜態成員staticSample2初始化:");
static {
System.out.println("Test的靜態代碼塊2");
}
private Sample sample2 = new Sample("sample2初始化:");
{
System.out.println("Test的非靜態代碼塊2");
}
public static void main(String args[]) {
new Test();
}
}
輸出結果:
Test的靜態代碼塊1
靜態成員staticSample1初始化::調用Sample的含參構造函數
靜態成員staticSample2初始化::調用Sample的含參構造函數
Test的靜態代碼塊2
Test的非靜態代碼塊1
sample1初始化::調用Sample的含參構造函數
sample2初始化::調用Sample的含參構造函數
Test的非靜態代碼塊2
調用Test的默認構造函數
二.考慮繼承的情況,一個類中的初始化順序是:
1.繼承體系中所有的靜態變量初始化(先父類,後子類)
2.父類初始化(普通成員先初始化,構造函數的調用)
3.子類初始化(普通成員先初始化,構造函數的調用)
舉個例子:
class Sample {
public Sample(String s) {
System.out.println(s);
}
}
class Father {
public Father() {
System.out.println("調用Father默認構造函數");
}
static {
System.out.println("父類-靜態代碼塊1");
}
private Sample sample1 = new Sample("父類-成員sample1初始化");
static private Sample fatheStaticSample1 = new Sample(
"父類-靜態成員fatheStaticSample1初始化");
static {
System.out.println("父類-靜態代碼塊2");
}
private Sample sample2 = new Sample("父類-成員sample2初始化");
static private Sample fatheStaticSample2 = new Sample(
"父類-靜態成員fatheStaticSample2初始化");
}
class Child extends Father {
public Child() {
System.out.println("調用Child默認構造函數");
}
static private Sample childStaticSample1 = new Sample(
"子類-靜態成員childStaticSample1初始化");
private Sample sample1 = new Sample("子類-成員sample1初始化");
static {
System.out.println("子類-靜態代碼塊1");
}
private Sample sample2 = new Sample("子類-成員sample2初始化");
static private Sample childStaticSample2 = new Sample(
"子類-靜態成員childStaticSample2初始化");
static {
System.out.println("子類-靜態代碼塊2");
}
}
public class Test {
public Test() {
System.out.println("調用Test的默認構造函數");
}
public static void main(String args[]) {
System.out.println("main函數");
new Child();
System.out.println("已經構造完Child對象");
}
}
運行結果:
main函數
父類-靜態代碼塊1
父類-靜態成員fatheStaticSample1初始化
父類-靜態代碼塊2
父類-靜態成員fatheStaticSample2初始化
--------------------父類靜態成員初始化
子類-靜態成員childStaticSample1初始化
子類-靜態代碼塊1
子類-靜態成員childStaticSample2初始化
子類-靜態代碼塊2
--------------------子類靜態成員初始化
父類-成員sample1初始化
父類-成員sample2初始化
調用Father默認構造函數
--------------------父類普通成員初始化和調用構造函數
子類-成員sample1初始化
子類-成員sample2初始化
調用Child默認構造函數
---------------------子類普通成員初始化和調用構造函數
最後附上圖一張,幫助理解!
參考鏈接:
http://www.cnblogs.com/miniwiki/archive/2011/03/25/1995615.html(這個寫的很好,本博文大多參考於此)
http://wangleide414.iteye.com/blog/515732
http://blog.sina.com.cn/s/blog_4cc16fc50100bjjp.html