類的實例化順序:先是類初始化(執行類的靜態初始化塊),再是實例初始化(執行類的普通初始化塊、構造器)
類初始化的順序是:java.lang.Object類--->中間的父類......--->當前初始化的類(先執行最頂層父類的靜態初始化塊,然后依次向下,直到執行當前類的靜態初始化塊)
實例初始化的順序是:java.lang.Object類--->中間的父類......--->當前初始化的類(先執行最頂層父類的普通初始化塊、最頂層父類的構造器,然后依次向下,直到執行當前類的普通初始化塊、當前類的構造器)
代碼實例如下:
import static java.lang.System.*;
class Root{
static{
out.println("Root類靜態初始化塊!");
}
{
out.println("Root類普通初始化塊!");
}
public Root(){
out.println("Root類無參數構造器!");
}
}
class Mid extends Root{
static{
out.println("Mid類靜態初始化塊!");
}
{
out.println("Mid類普通初始化塊!");
}
public Mid(){
out.println("Mid類無參數構造器!");
}
public Mid(String name){
out.println("Mid類一個參數的構造器:name="+name);
}
}
class Leaf extends Mid{
static{
out.println("Leaf類靜態初始化塊!");
out.println();
}
{
out.println("Leaf類普通初始化塊!");
}
public Leaf(){
out.println("Leaf類無參數構造器!");
}
}
public class Test{
public static void main(String[] args){
Leaf leaf=new Leaf();
}
}
運行結果:

從結果可以看出,結果前三行為類初始化階段執行的兩個父類和自己類中的靜態初始化塊,后六行為類實例化階段執行的兩個父類和自己類中的普通靜態初始化塊、構造器。
把代碼稍微改造一下,仔細體會其中的調用順序變化:
import static java.lang.System.*;
class Root{
static{
out.println("Root類靜態初始化塊!");
}
{
out.println("Root類普通初始化塊!");
}
public Root(){
out.println("Root類無參數構造器!");
}
}
class Mid extends Root{
static{
out.println("Mid類靜態初始化塊!");
}
{
out.println("Mid類普通初始化塊!");
}
public Mid(){
out.println("Mid類無參數構造器!");
}
public Mid(String name){
//-改動:調用本類構造器
this();
out.println("Mid類一個參數的構造器:name="+name);
}
}
class Leaf extends Mid{
static{
out.println("Leaf類靜態初始化塊!");
out.println();
}
{
out.println("Leaf類普通初始化塊!");
}
public Leaf(){
//-改動:調用父類一個參數構造器
super("張三");
out.println("Leaf類無參數構造器!");
}
}
public class Test{
public static void main(String[] args){
Leaf leaf=new Leaf();
}
}
運行結果:

對Leaf類二次實例化:
import static java.lang.System.*;
class Root{
static{
out.println("Root類靜態初始化塊!");
}
{
out.println("Root類普通初始化塊!");
}
public Root(){
out.println("Root類無參數構造器!");
}
}
class Mid extends Root{
static{
out.println("Mid類靜態初始化塊!");
}
{
out.println("Mid類普通初始化塊!");
}
public Mid(){
out.println("Mid類無參數構造器!");
}
public Mid(String name){
//-改動:調用本類構造器
this();
out.println("Mid類一個參數的構造器:name="+name);
}
}
class Leaf extends Mid{
static{
out.println("Leaf類靜態初始化塊!");
out.println();
}
{
out.println("Leaf類普通初始化塊!");
}
public Leaf(){
//-改動:調用父類一個參數構造器
super("張三");
out.println("Leaf類無參數構造器!");
out.println();
}
}
public class Test{
public static void main(String[] args){
Leaf leaf1=new Leaf();
Leaf leaf2=new Leaf();//-二次改動,第二次實例化
}
}
運行效果:

總結:
1、Java加載並初始化某個類時,總是保證該類所有父類(包括直接和間接)全部加載並初始化
2、如上效果所示:類初始化成功后,會在虛擬機里一直存在,因此當第二次實例化時,不會再進行類初始化了
