1. 程式人生 > 其它 >Java修飾符 --- static

Java修飾符 --- static

@

目錄

一、靜態變數和靜態方法

  1. 被 static 修飾的變數為類變數,也就是靜態變數,可以直接通過類名.變數名引用,也可以通過 new 例項物件呼叫
  2. 被 static 修飾的方法為類方法,也就是靜態方法,可以直接通過類名.方法名引用,也可以通過 new 例項物件呼叫
  3. 靜態變數和靜態方法統一屬於類的靜態資源,是類例項之間共享的,也就是一處變,到處變,是同步的,生命週期長,隨類的建立而生,隨類的結束而結束

二、靜態變數和非靜態變數的區別?

  1. 靜態變數是屬於類的,當且僅當在類初始化的時候載入,在記憶體只有一個副本,被所有物件(類例項)共享

  2. 非靜態變數是物件的,每次建立物件的時候初始化,存在多個副本,各個物件擁有的副本互不影響

  3. 靜態變數是存放在方法區的,而非靜態變數在堆區

    方法區:存放已經載入的類資訊、常量、靜態變數以及方法程式碼的記憶體區域

    常量池:是方法區的一部分,主要用來存放常量和類中的符號引用等資訊

    堆區:用於存放類的物件例項
    棧區:也叫 Java 虛擬棧,由一個一個的棧幀組成的先進後出的棧式結構,棧幀中存放方法執行時產生的區域性變數、方法出口等資訊,當呼叫一個方法時,虛擬機器棧會建立一個棧幀存放這些資料,當方法完成時,棧幀消失,如果方法中呼叫了其他方法,則繼續在棧頂建立新的棧幀

三、關於靜態方法能否引用非靜態資源等問題?

  • 例子:

    public class staticTest {
        
        private int number = 333;
        
        public static void main(String[] args) {
            number = 1;
        }
    
    }
    

    這段程式碼編譯都不會通過,執行的話會報錯:無法從靜態上下文中引用非靜態變數

    原因:

    靜態資源屬於類,但是是獨立於類存在的,存在方法區(靜態區),JVM的類載入機制中,靜態資源是在類初始化的時候載入,而非靜態資源是在類new建立的時候載入,也就是說靜態資源的初始化早於非靜態資源。所有上述程式碼中,先執行 main 方法的時候,成員變數 number 還沒初始化。

    總結:

    靜態方法只能引用靜態資源,非靜態方法可以引用靜態資源和非靜態資源

四、靜態程式碼塊

用於初始化一個類的時候做操作用的,靜態塊裡的程式碼只在初始化的時候執行一次

執行順序(雙親委託載入):

  • 一個類:類內容(靜態變數、靜態初始化塊)=> 例項內容(變數、初始化塊、構造器)

  • 繼承關係類:父類(靜態變數、靜態初始化塊)=> 子類(靜態變數、靜態初始化塊)=> 父類(變數、初始化塊、構造器)=> 子類(變數、初始化塊、構造器)

  • 例子:

    public class staticTest {
    
        static {
            number = 333;
            System.out.println(number);
        }
        private static int number;
    
    }
    

    注意:上面程式碼列印會報錯:不能定義之前引用,也就是說:靜態程式碼塊對應定義在它之後的靜態變數,可以賦值,但是不能訪問

五、靜態內部類

  • 靜態內部類作用:

    1.內部類一般只為其外部類使用

    2.內部類存在外部類的引用,可以直接訪問外部類屬性

    每個內部類都能單獨繼承一個介面,而無論外部類是否已經繼承該介面(內部類使多重繼承的解決方案更加完美)

  • 外部類以物件的方式(建立物件訪問)使用內部類,可以訪問內部類所有的方法和屬性,包括私有方法和屬性

    內部類不能訪問外部類所在的區域性變數,只能訪問 final 修飾的區域性變數

    在方法內定義內部類時,如果內部類呼叫了方法中的變數,那麼該變數必須申明為final型別,為什麼?後來想到應該是生命週期的原因,因為方法內定義的變數是區域性變數,離開該方法,變數就失去了作用,也就會自動被消除,而內部類卻不會離開它所在方法就失去作用