之前一直只知道有靜態(tài)代碼塊锐锣。后來(lái)才知道還有一個(gè)非靜態(tài)代碼塊。
靜態(tài)代碼塊是指由 static
修飾的大括號(hào)里的一段代碼,那么非靜態(tài)代碼塊就是沒(méi)有修飾的大括號(hào)里的一段代碼光督。就像下面:
# 靜態(tài)代碼塊
static {
若干代碼,隨便寫(xiě)點(diǎn)啥吧塔粒。结借。。窗怒。
}
# 非靜態(tài)代碼塊
{
若干代碼映跟,隨便寫(xiě)點(diǎn)啥吧。扬虚。努隙。。
}
他們的共同特點(diǎn)是:方法名辜昵、作用域荸镊、返回值、參數(shù)一概沒(méi)有堪置。
詳情解析
我們先提出幾個(gè)問(wèn)題:
- 靜態(tài)和非靜態(tài)這兩種代碼塊的區(qū)別是什么躬存?
- 它們之間的執(zhí)行順序是怎么樣?和構(gòu)造函數(shù)間的執(zhí)行順序又是怎么樣的舀锨?
- 當(dāng)有繼承情況存在的時(shí)候岭洲,它們的執(zhí)行順序又是怎么樣?
帶著問(wèn)題坎匿,進(jìn)行接下來(lái)的代碼分析:
package com.sunyu.javaBase.aboutClass;
public class LoadOrder {
public static void main(String[] args) {
/**
一般情況下的代碼測(cè)試
*/
parentTest();
/**
* 有繼承情況存在下的代碼測(cè)試
*/
childrenTest();
}
/**
* 父類測(cè)試
*/
public static void parentTest() {
Parent parent = new Parent();
System.out.println();
System.out.println("-------- 這是兩次實(shí)例化的分割線 ---------");
System.out.println();
parent = new Parent("父類測(cè)試");
}
/**
* 子類測(cè)試
*/
public static void childrenTest() {
Children children = new Children();
System.out.println();
System.out.println("-------- 這是兩次實(shí)例化的分割線 ---------");
System.out.println();
children = new Children("子類測(cè)試");
}
}
class Parent {
{
System.out.println("父類:執(zhí)行非靜態(tài)代碼塊");
}
static {
System.out.println("父類:執(zhí)行靜態(tài)代碼塊");
}
static String name;
Parent() {
System.out.println("父類:執(zhí)行無(wú)參構(gòu)造函數(shù)");
}
Parent(String name) {
System.out.println("父類:執(zhí)行有參構(gòu)造函數(shù) --->" + name);
}
}
class Children extends Parent {
{
System.out.println("子類:執(zhí)行非靜態(tài)代碼塊");
}
static {
System.out.println("子類:執(zhí)行靜態(tài)代碼塊");
}
static String name;
Children() {
System.out.println("子類:執(zhí)行無(wú)參構(gòu)造函數(shù)");
}
Children(String name) {
System.out.println("子類:執(zhí)行有參構(gòu)造函數(shù) --->" + name);
}
}
在上面的代碼中定義了:主類 LoadOrder
盾剩,父類 Parent
,子類 Children
替蔬。
執(zhí)行
parentTest()
告私,測(cè)試代碼塊之間,以及代碼塊與構(gòu)造函數(shù)之間的執(zhí)行順序承桥。執(zhí)行結(jié)果如下:
在parentTest()
中 Parent 實(shí)例化了兩次驻粟。從上面的執(zhí)行結(jié)果來(lái)看:
- 靜態(tài)代碼塊執(zhí)行了一次。眾所周知凶异,是類在初始化的時(shí)候執(zhí)行的蜀撑,也只執(zhí)行這一次挤巡。
- 非靜態(tài)代碼塊執(zhí)行了兩次,而 Parent 實(shí)例化了兩次屯掖。則非靜態(tài)代碼塊是在類被實(shí)例化的時(shí)候執(zhí)行的玄柏,類每實(shí)例化一次,則非靜態(tài)代碼塊執(zhí)行一次
- 兩種代碼塊的執(zhí)行順序都在構(gòu)造函數(shù)之前贴铜。但是靜態(tài)代碼塊在非靜態(tài)之前粪摘。
執(zhí)行
childrenTest()
,測(cè)試在繼承情況下绍坝,代碼塊徘意,構(gòu)造函數(shù)間的執(zhí)行順序。執(zhí)行結(jié)果如下:
在childrenTest()
中轩褐,Children 實(shí)例化了兩次椎咧。從上面的執(zhí)行結(jié)果看:
- 不管是父類還是子類,靜態(tài)代碼塊優(yōu)先執(zhí)行把介。
- 在所有的靜態(tài)代碼塊執(zhí)行完后勤讽,執(zhí)行父類相關(guān)的代碼。先執(zhí)行父類非靜態(tài)代碼塊拗踢,再執(zhí)行父類構(gòu)造方法脚牍;之后執(zhí)行子類非靜態(tài)代碼塊,再執(zhí)行子類構(gòu)造方法
結(jié)論
- 靜態(tài)代碼塊是在類被加載的時(shí)候(即初始化)去執(zhí)行巢墅,且只執(zhí)行一次
- 非靜態(tài)代碼塊是在類被實(shí)例化的時(shí)候執(zhí)行诸狭。每被實(shí)例化一次,就會(huì)被執(zhí)行一次君纫。
- 在無(wú)繼承的情況下:執(zhí)行順序?yàn)椋红o態(tài)代碼塊 ——> 非靜態(tài)代碼塊 ——> 構(gòu)造函數(shù)
- 在有繼承的情況下:執(zhí)行順序?yàn)椋焊割愌庇觯宇愳o態(tài)方法 ——> 父類非靜態(tài)代碼塊、構(gòu)造函數(shù) ——> 子類非靜態(tài)代碼塊蓄髓、構(gòu)造函數(shù)