天天看點

[java] static關鍵字總結

Table of Contents

概述

修飾類的變量

修飾方法

修飾代碼塊

靜态導入包

用法

static關鍵字與java記憶體

概述

static 在java體系裡的地位:java語言的一個修飾符,屬于非通路修飾符,所謂通路修飾符就是控制通路權限的修飾符,如public,protected,private,default

再來看看static翻譯成中文的意思:靜止的; 靜電的; 不變的; [物] 靜力的。顯而易見,在程式設計語言中最準确的意思應該取的意思是 靜止的,不變的較為準确.

一般來說,當建立類時,就是在描述那個類的的對象的外觀和行為,除非用new建立那個類的對象,否則,實際上并未獲得任何對象。執行new來建立對象時,資料存儲空間才被配置設定,其方法才供外界調用。但兩種情形是以上方法無法解決的。

  1. 一種是隻想為某特定域配置設定單一存儲空間,而不去考慮究竟要建立什麼對象,甚至根本就不建立任何對象。
  2. 另一種是希望某個方法不與包含它的類的任何對象關聯在一起。也就是說,即使沒有建立對象,也能調用這個方法

Static關鍵字就是為了滿足這兩方面的需要。

當聲明一個事物(注意:是一個事物,一個方法一個變量都是一個事物),當聲明一個事物是static時,就意味着這個域或方法不會與包含它的那個類的任何對象事例關聯在一起。是以,即使從未建立某類的任何對象,也可以調用其static方法或者通路其static域。static關鍵字的用途簡言之就是友善在沒有建立任何對象的前提下,僅僅通過類本身來調用static方法/變量。static可以用來修飾類的成員方法、類的成員變量,另外可以編寫static代碼塊來優化程式性能。

 static方法和字段的一個重要用法就是在不建立任何對象的前提下就可以調用它。這一點對main方法很重要,main 方法是我們的應用程式入口。

靜态變量存儲在metaspace,即以前的方法區。

static關鍵字主要的用法有如下幾種

修飾類的變量

用static修飾的變量

(1) 用static關鍵字修飾的變量成為靜态變量.

(2)用static修飾的變量屬于一個類,他在jvm記憶體中的配置設定區域是一塊不變區域,可以稱之為靜态存儲區

(3)靜态變量的加載是在類加載時完成初始化的。它在記憶體中隻有一份, 一般在對象中共享資料時才定義static的變量。

此外,static變量是屬于類的,不屬于類的某一個對象,static變量存放的區域叫做:PermGem Sections,而我們知道對象是存放在堆(heap)上的。

沒有用static關鍵字修飾的變量稱為執行個體變量,用static修飾的是類變量

(1)執行個體變量是伴随着一個執行個體,一個對象的,他的生命周期與該對象一緻。

(2)執行個體變量在記憶體中配置設定給每一個對象,每一個執行個體變量都是屬于一個對象的。

修飾方法

類的靜态成員(變量和方法)屬于類本身(注意是類本身,不是某一個對象),在類加載的時候就會配置設定記憶體,可以通過類名直接去通路. static修飾的方法是屬于類的一個方法,不需要建立對象就可以調用。

非static方法隻能在對象被建立之後才能調用。

static隻能直接調用類的static方法,不能直接調用非static方法,若要調用非static方法,需要new相應的類的執行個體,再通過他來調用。 原因在于:

程式最終都将在記憶體中執行,變量隻有在記憶體中占有一席之地時才能被通路。

類的靜态成員(變量和方法)屬于類本身,在類加載的時候就會配置設定記憶體,可以通過類名直接去通路;非靜态成員(變量和方法)屬于類的對象,是以隻有在類的對象産生(建立類的執行個體)時才會配置設定記憶體,然後通過類的對象(執行個體)去通路。

詳細參考:https://www.cnblogs.com/wxw7blog/p/7053212.html 

修飾代碼塊

static代碼塊是獨立于成員變量和成員函數的代碼塊。隻會在JVM加載類時會執行這些靜态的代碼塊,且隻被執行一次。

靜态導入包

采用static導入包後,在不與目前類的方法名沖突的情況下,無需使用“類名.方法名”的方法去調用類方法了,直接可以采用"方法名"去調用類方法,就和調用類自己的方法一樣

用法

對于靜态字段,隻有直接定義這個字段的類才會被初始化,是以通過其子類來引用父類中定義的靜态字段,隻會觸發父類的初始化而不會觸發子類的初始化。至于是否要觸發子類的加載和驗證,在虛拟機中并未明确規定,這取決于虛拟機的具體實作。例如:

public class SuperClass {
    static {
        System.out.println("SupperClass init");
    }

    public static int value = 123;
}
           
public class NoInitialization {
    public static void main(String[] args){
        System.out.println(SubClass.value);
        //對于靜态字段,隻有直接定義這個字段的類才會被初始化
    }
}
           
public class SubClass extends SuperClass {
    static {
        System.out.println("SubClass init");
    }
}
           

上面這個程式的輸出結果如下:

SupperClass init
123
           

但是這兒有個問題,根據static代碼塊的定義,在類加載時,static代碼塊會被執行一次,那麼這裡子類難道沒有被虛拟機加載嗎?事實上這取決于虛拟機的實作,在sun HotSpot虛拟機中,可以通過-XX:+TraceClassLoading參數觀察到此操作會導緻子類的加載。

static關鍵字與java記憶體

從java虛拟機的的記憶體角度分析,static修飾的變量存儲于方法區,而不是一般字段的堆記憶體。這意味着,static變量并不存在生命周期一說。并且其垃圾收集和普通對象的垃圾收集也是不一樣的。