java靜態(tài)代碼塊、靜態(tài)方法、靜態(tài)變量、構(gòu)造代碼塊、普通代碼塊

一、靜態(tài)代碼塊

  • 在java類(lèi)中(方法中不能存在靜態(tài)代碼塊)使用static關(guān)鍵字和{}聲明的代碼塊:
public class CodeBlock{
    static{
        System.out.println("靜態(tài)代碼塊");  
    }      
}
  • 執(zhí)行時(shí)機(jī)
    靜態(tài)代碼塊在類(lèi)被加載的時(shí)候就運(yùn)行了,而且只運(yùn)行一次, 并且優(yōu)先于各種代碼塊以及構(gòu)造函數(shù)。如果一個(gè)類(lèi)中有多個(gè)靜態(tài)代碼塊,就會(huì)按照書(shū)寫(xiě)的順序執(zhí)行。

  • 靜態(tài)代碼塊的作用
    一般情況下,如果有些代碼需要在項(xiàng)目啟動(dòng)的時(shí)候執(zhí)行,這時(shí)就需要靜態(tài)代碼快,比如一個(gè)項(xiàng)目啟動(dòng)需要加載很多配置文件等資源,就可以都放在靜態(tài)代碼塊中。

  • 靜態(tài)代碼塊不能存在于任何方法體中
    這個(gè)很好理解,首先要明確靜態(tài)代碼塊是在類(lèi)加載的時(shí)候就運(yùn)行了,我們分情況進(jìn)行討論:

    1. 對(duì)于普通方法,由于普通方法是通過(guò)加載類(lèi),然后new出實(shí)例化對(duì)象,通過(guò)對(duì)象才能運(yùn)行這個(gè)方法,而靜態(tài)代碼塊只需要加載類(lèi)之后就能運(yùn)行了。

    2. 對(duì)于靜態(tài)方法,在類(lèi)加載的時(shí)候,靜態(tài)方法就已經(jīng)加載了,但是我們必須通過(guò)類(lèi)名或者對(duì)象名才能進(jìn)行訪問(wèn),也就是說(shuō)相對(duì)于靜態(tài)代碼塊,靜態(tài)代碼塊是主動(dòng)運(yùn)行的,而靜態(tài)方法是被動(dòng)運(yùn)行的。

    3. 不管哪種方法,我們需要明確的是靜態(tài)代碼塊的存在在類(lèi)加載的時(shí)候就自動(dòng)運(yùn)行了,而放在不管是普通方法中還是靜態(tài)方法中,都是不能自動(dòng)運(yùn)行的。

  • 靜態(tài)代碼塊不能訪問(wèn)普通代變量
    這個(gè)理解思維同上,普通代碼塊只能通過(guò)對(duì)象來(lái)進(jìn)行調(diào)用,而不能防砸靜態(tài)代碼塊中。

二、構(gòu)造代碼塊

  • 格式:java類(lèi)中使用{}聲明的代碼塊(和靜態(tài)代碼塊的區(qū)別是少了static關(guān)鍵字)
public class codeBlock {
    static {
        System.out.println("靜態(tài)代碼塊");
    }
    {
        System.out.println("構(gòu)造代碼塊");
    }
}
  • 執(zhí)行時(shí)機(jī)
    構(gòu)造代碼塊在創(chuàng)建對(duì)象的時(shí)候被調(diào)用,每創(chuàng)建一次對(duì)象都會(huì)調(diào)用一次,但是優(yōu)先于構(gòu)造函數(shù)執(zhí)行,需要注意的是,聽(tīng)名字我們就知道,構(gòu)造代碼塊不是優(yōu)先于構(gòu)造函數(shù)執(zhí)行的,而是依托于構(gòu)造函數(shù),也就是說(shuō),如果你不實(shí)例化對(duì)象,構(gòu)造代碼塊是不會(huì)執(zhí)行的。怎么理解呢?先看看下面的代碼段:
public class codeBlock {
    static {
        System.out.println("靜態(tài)代碼塊");
    }
    {
        System.out.println("構(gòu)造代碼塊");
    }
    public codeBlock(){
        System.out.println("無(wú)參構(gòu)造函數(shù)");
    }
    public codeBlock(String str){
        System.out.println("有參構(gòu)造函數(shù)");
    }
}

我們反編譯生成的.class文件

import java.io.PrintStream
public class codeBlock {
    public codeBlock(){
        System.out.println("構(gòu)造代碼塊");
        System.out.println("無(wú)參構(gòu)造函數(shù)");
    }
    public codeBlock(String str){
        System.out.println("構(gòu)造代碼塊");
        System.out.println("有參構(gòu)造函數(shù)");
    }
}
  • 構(gòu)造代碼塊的作用
    1. 和構(gòu)造函數(shù)的作用類(lèi)似,都能夠?qū)ο笥浶猿跏蓟⑶抑灰獎(jiǎng)?chuàng)建一個(gè)對(duì)象,構(gòu)造代碼塊都會(huì)執(zhí)行一次。但是反過(guò)來(lái),構(gòu)造函數(shù)則不會(huì)再每個(gè)對(duì)象創(chuàng)建的時(shí)候都執(zhí)行(多個(gè)構(gòu)造函數(shù)的情況下,建立對(duì)象時(shí)傳入的參數(shù)不同則初始化使用對(duì)應(yīng)的構(gòu)造函數(shù))

    2. 利用每次創(chuàng)建對(duì)象的時(shí)候都會(huì)提前調(diào)用一次構(gòu)造代碼塊特性,我們做諸如統(tǒng)計(jì)創(chuàng)建對(duì)象的次數(shù)等功能。

三、構(gòu)造函數(shù)

  • 構(gòu)造函數(shù)必須和類(lèi)名完全相同。在java中,普通函數(shù)可以和構(gòu)造函數(shù)同名,但是必須帶有返回值。

  • 構(gòu)造函數(shù)的功能主要用于在類(lèi)創(chuàng)建時(shí)定義初始化的狀態(tài)。沒(méi)有返回值,也不能用void來(lái)進(jìn)行修飾。這就保證額它不僅什么也不用自動(dòng)返回,而且根本不能有任何選擇,而其他方法都有返回值,盡管方法體本身不會(huì)自動(dòng)返回什么,但是仍然可以返回一些東西,而這些東西可能是不安全的;

  • 構(gòu)造函數(shù)不能被直接調(diào)用,必須通過(guò)New運(yùn)算符在創(chuàng)建對(duì)象的時(shí)才會(huì)自動(dòng)調(diào)用;而一般的方法是在程序執(zhí)行到它的時(shí)候被調(diào)用的

  • 當(dāng)定義一個(gè)類(lèi)的時(shí)候,通常情況下都會(huì)現(xiàn)實(shí)該類(lèi)的構(gòu)造函數(shù),并在函數(shù)中指定初始化的工作也可省略,不過(guò)Java編譯期會(huì)提供一個(gè)默認(rèn)的構(gòu)造函數(shù),此默認(rèn)的構(gòu)造函數(shù)是不帶參數(shù)的,即空參構(gòu)造。而一般的方法不存在這一特點(diǎn)。

四、普通代碼塊

通代碼塊和構(gòu)造代碼塊的區(qū)別是,構(gòu)造代碼塊是在類(lèi)中定義的,而普通代碼塊是在方法體重定義的。并且普通代碼塊的執(zhí)行順序和書(shū)寫(xiě)順序是一致的

public class sayHelllo {
    {
        System.out.println("普通代碼塊");
    }
}

五、執(zhí)行順序

靜態(tài)代碼塊>構(gòu)造代碼塊>構(gòu)造函數(shù)>普通代碼塊

public class codeBlock {
    static {
        System.out.println("靜態(tài)代碼塊");
    }
    {
        System.out.println("構(gòu)造代碼塊");
    }
    public codeBlock(){
        System.out.println("無(wú)參構(gòu)造函數(shù)");
    }
    public codeBlock(String str){
        System.out.println("有參構(gòu)造函數(shù)");
    }
    public void sayHello(){
        System.out.println("普通代碼塊");
    }

    public static void main(String[] args) {
        System.out.println("執(zhí)行了main方法");

        new codeBlock().sayHello();

        System.out.println("---------------------------");

        new codeBlock().sayHello();
    }
}
1441368-20190307091009680-1897549312.png

六、實(shí)例

public class Test1 {

    static {
        int x = 5;
    }

    static  int x,y;

    public static void main(String[] args) {
        x--; // 步驟一  x沒(méi)有設(shè)初始值初始值就是0,
        myMethod(); // 運(yùn)行myMethod方法,x之前是-1,開(kāi)始調(diào)用myMethod()函數(shù)
        System.out.println(x+y++ +x); // 輸出 2,y=1
    }

    public static void myMethod()
    {
        y = x++ + ++x; //步驟2:這個(gè)地方的調(diào)用要注意:x++ + ++x 是將-1先自加然后加1,得到y(tǒng)=0  
        System.out.println(x);  // x= 1
        System.out.println(y); // y = 0
    }
}

執(zhí)行過(guò)程分析:

1. static { int x =5;}  //靜態(tài)代碼塊,在類(lèi)加載的時(shí)候回被加載并且執(zhí)行,但是由于是局部變量,所以x= 5 不影響后面的值

2. static int x,y;  這個(gè)時(shí)候會(huì)將x和y進(jìn)行初始化,得到x=0;y=0

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容