1. 靜態代碼塊
靜態代碼塊:定義在類中方法外,使用static修飾
①可以為類變量(靜態變量)初始化
②靜態代碼塊在第一次使用這個類之前執行,即在類初始化時執行,且只執行一次
③若有多個靜態代碼塊,那么按照定義的先后順序依次執行
④在靜態代碼塊中不能訪問非靜態成員(屬性、方法、內部類)
⑤在靜態代碼塊中不能使用this和super關鍵字
⑥靜態代碼塊的執行優先於main方法、非靜態代碼塊和構造方法的執行
⑦父類靜態代碼塊的執行優先於子類靜態代碼塊執行
代碼示例:
public class StaticBlockTest {
public static void main(String[] args) {
MyClass.show();
MyClass.show();
MyClass.show();
}
static {
System.out.println("StaticBlockTest類靜態代碼塊");
}
}
class MyClass {
static {
System.out.println("MyClass類靜態代碼塊1");
}
public static void show() {
System.out.println("MyClass類靜態方法");
}
static {
System.out.println("MyClass類靜態代碼塊2");
}
}
運行結果:
StaticBlockTest類靜態代碼塊
MyClass類靜態代碼塊1
MyClass類靜態代碼塊2
MyClass類靜態方法
MyClass類靜態方法
MyClass類靜態方法
2. 類初始化
類初始化即執行類初始化方法:<clinit>()
類初始化方法,一個類只有一個。它也是由編譯器編譯生成的,由兩部分代碼組成:
①靜態變量的顯式賦值代碼
②靜態代碼塊的代碼
其中①和②是按定義的先后順序依次執行的
代碼示例:
public class InitTest {
public static void main(String[] args) {
MyClass my = new MyClass();
}
}
class MyClass {
static {
System.out.println("MyClass類靜態代碼塊1");
}
private static String str = assingn();
public static void show() {
System.out.println("MyClass類靜態方法");
}
private static String assingn() {
System.out.println("assign()方法為靜態變量顯式賦值");
return "java";
}
static {
System.out.println("MyClass類靜態代碼塊2");
}
}
運行結果:
MyClass類靜態代碼塊1
assign()方法為靜態變量顯式賦值
MyClass類靜態代碼塊2
3. 子類初始化
一個類初始化時會先檢查它的父類是否初始化,如果父類沒有初始化,那么會先初始化父類
(1)父類的初始化
-
父類的靜態變量的顯式賦值
-
父類的靜態代碼塊
(2)子類的初始化
-
父類的靜態變量的顯式賦值
-
父類的靜態代碼塊
代碼示例:
public class InitTest2 {
public static void main(String[] args) {
/*Father f = new Father();
System.out.println("--------分隔線---------");*/
Son s = new Son();
}
}
class Father{
private static String info = assign();
static{
System.out.println("父類的靜態代碼塊");
}
//靜態方法不能被重寫
public static String assign(){
System.out.println("父類assign()方法");
return "Father";
}
}
class Son extends Father{
private static String info = assign();
static{
System.out.println("子類的靜態代碼塊");
}
public static String assign(){
System.out.println("子類assign()方法");
return "Son";
}
}
運行結果:
父類assign()方法
父類的靜態代碼塊
子類assign()方法
子類的靜態代碼塊
4. 類初始化和實例初始化結合
先執行類初始化,后執行實例初始化
代碼示例:
public class InitTest3 {
public static void main(String[] args) {
Demo d = new Demo();
}
}
class Demo{
{
System.out.println("非靜態代碼塊1");
}
static{
System.out.println("靜態代碼塊1");
}
public Demo(){
System.out.println("無參構造");
}
private static String info = assignInfo();
private String msg = assignMsg();
static{
System.out.println("靜態代碼塊2");
}
{
System.out.println("非靜態代碼塊2");
}
public static String assignInfo(){
System.out.println("assignInfo()方法");
return "hello";
}
public String assignMsg(){
System.out.println("assignMsg()方法");
return "msg";
}
}
運行結果:
靜態代碼塊1
assignInfo()方法
靜態代碼塊2
非靜態代碼塊1
assignMsg()方法
非靜態代碼塊2
無參構造
5. 子類初始化和子類實例初始化結合
執行順序:①父類的類初始化 => ②子類的類初始化 => ③父類的實例初始化方法 => ④子類的實例初始化方法
public class InitTest4 {
public static void main(String[] args) {
//Father f = new Father();
Son s = new Son();
}
}
class Father {
{
System.out.println("父類非靜態代碼塊1");
}
static {
System.out.println("父類靜態代碼塊1");
}
private static String info = assignInfo();
private String msg = assignMsg();
public Father() {
System.out.println("父類無參構造");
}
static {
System.out.println("父類靜態代碼塊2");
}
{
System.out.println("父類非靜態代碼塊2");
}
public static String assignInfo() {
System.out.println("父類assignInfo()方法");
return "hello";
}
public String assignMsg() {
System.out.println("父類assignMsg()方法");
return "msg";
}
}
class Son extends Father {
{
System.out.println("子類非靜態代碼塊1");
}
static {
System.out.println("子類靜態代碼塊1");
}
private static String info = assignInfo();
private String msg = assignMsg();
public Son() {
System.out.println("子類無參構造");
}
static {
System.out.println("子類靜態代碼塊2");
}
{
System.out.println("子類非靜態代碼塊2");
}
public static String assignInfo() {
System.out.println("子類assignInfo()方法");
return "hello";
}
public String assignMsg() {
System.out.println("子類assignMsg()方法");
return "msg";
}
}
父類靜態代碼塊1
父類assignInfo()方法
父類靜態代碼塊2
子類靜態代碼塊1
子類assignInfo()方法
子類靜態代碼塊2
父類非靜態代碼塊1
子類assignMsg()方法
父類非靜態代碼塊2
父類無參構造
子類非靜態代碼塊1
子類assignMsg()方法
子類非靜態代碼塊2
子類無參構造