public class InitObject {
private int id;
private String name;
private static int age;
public InitObject(){
System.out.println(id);
System.out.println(name);
System.out.println(age);
}
public static void main(String[] args) {
new InitObject();
}
}
輸出結果:
0
null
0
從輸出結果可以知道,一個類的所有成員變量無論是靜態還是非靜態的,都已經在調用構造方法之前被初始化過了。
public class StaticInitialization {
public static void main(String[] args) {
System.out.println("start");
new Market();
System.out.println("end");
}
static Shop shop = new Shop();
static Market market = new Market();
}
class Apple {
public Apple(int num) {
System.out.println("apple" + num);
}
}
class Shop {
Apple apple = new Apple(1);
static Apple apple2 = new Apple(2);
public Shop() {
System.out.println("shop");
}
}
class Market {
Apple apple = new Apple(1);
public Market() {
System.out.println("Market");
}
static Apple apple2 = new Apple(2);
}
輸出結果:
apple2
apple1
shop
apple2
apple1
Market
start
apple1
Market
end
從輸出結果可以看到靜態數據只在必要時初始化,如果不創建Shop或者沒有調用Shop中的靜態方法或變 量,那麼Shop中的靜態數據永遠也不會被初始化,
只有在第一個Shop對象被創建或者第一次訪問靜態數據的時候,靜態成員變量纔會被初始化,此後,無論靜態對象不會再次被初始化。
初始化對象的順序:先靜態對象然後是非靜態對象
下面以一道阿里巴巴的面試題來試試手
public class Alibaba {
public static int k = 0;
public static Alibaba t1 = new Alibaba("t1");
public static Alibaba t2 = new Alibaba("t2");
public static int i = print("i");
public static int n = 99;
private int a = 0;
public int j = print("j");
{
print("構造塊");
}
static {
print("靜態塊");
}
public Alibaba(String str) {
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
++i;
++n;
}
public static int print(String str) {
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
++n;
return ++i;
}
public static void main(String args[]) {
Alibaba t = new Alibaba("init");
}
}
根據初始化原則:有靜態數據先初始化靜態數據
k=0 t1=null t2=null i=0 n=0 又由於存在對靜態數據的顯示賦值: t1=new Alibaba("t1"); 這步之前會先初始類中的非靜態的成員變量 所以會調用j=print("j"); 1:j i=0 n=0 由於存在構造塊 2:構造塊 i=1 n=1 然後調用構造方法 3:t1 i=2 n=2 接着初始化t2: 4:j i=3 n=3 5:構造塊 i=4 n=4 6:t2 i=5 n=5 下一步爲靜態變量i賦值: 7:i i=6 n=6 接下來就是初始化靜態塊,然後是初始化非靜態的成員變量然後執行構造塊(如果有的話) 最後執行構造方法。