1. 程式人生 > 程式設計 >java關鍵字static的使用詳解

java關鍵字static的使用詳解

關鍵字 static

1. 概述

  • static 是一種修飾符
  • static 是Java中表靜態的關鍵字
  • 它可以修飾成員變數、成員方法、程式碼塊
  • 被static修飾的成員變數或成員方法,將不再依賴於物件的建立而去使用,而是依賴類的存在,成為類成員或類方法,是共享的(下面將會詳細的解釋)。

2. static修飾成員變數

2.1 常見的修飾符

  • public 修飾符
  • private 修飾符
  • 沒有修飾符
  • static 修飾符(靜態修飾符)
class Test {
	// public 修飾符
	public int a;
	// private 修飾符
	private int b;
	// 沒有修飾符
	int c;
	// static 修飾符
	public static int d;
}

2.2 記憶體圖分析講解static修飾成員變數

class Test {
	public int a;
	public String b;
	public double c;
	public static int d;
}
Test t = new Test();

以上述簡單的測試類為例,畫其底層的記憶體圖(下圖是我自己手畫的圖,天生手殘,請大家多擔待😂):

在這裡插入圖片描述

以上就是很簡單的Java例項化物件從建立記憶體到給成員變數開闢記憶體空間,並預設初始化的底層記憶體圖,我來解釋以下上面的圖:

  1. 在棧中開闢一塊記憶體,以main標識的記憶體空間,為main方法的函式幀。
  2. 在main函式幀標識的記憶體中,開闢一塊以t標識(例項化物件的名字)的區域性變數記憶體,其中存放的是地址值(或稱引用值),指向堆空間中儲存成員變數記憶體的首地址。
  3. 堆空間開闢一塊記憶體,用來存放成員變數,其開闢記憶體的個數於其成員變數的個數有關,以次Test為例,非static修飾的變數有3個,變在其中開闢三塊記憶體空間,用來存放著三個變數,順序為類中定義變數的順序。將該記憶體地址的首地址賦給棧中t標識的那塊記憶體。
  4. 因為成員變數在堆中開闢的記憶體,堆的機制,存在預設初始化,所以對成員變數賦予預設初始化的值,int,double,屬於基本資料型別,所以直接將其預設值0,0.0寫入對應的記憶體當中;成員變數c為字元型,為引用資料型別,所以其記憶體中存放的是地址值,指向堆中的另一塊空間,並賦予預設值null,完成成員變數的初始化。
  5. 從圖中可以很明顯的看出,存放d,用static修飾的成員變數,其記憶體的開闢不在堆記憶體中開闢,而是在方法區中的靜態區開闢(可以理解靜態區就在方法區當中)。
  6. 靜態區隨類的載入而開闢,且其中的存放的靜態成員變數是共享的,且僅有次一塊記憶體。

2.3 static修飾的成員變數的特點

  • static修飾的成員變數不再是普通的成員變數,而是類成員變數
  • 其隨著類的載入而載入,隨著類的載入而開闢記憶體,不依賴於物件的存在
  • 其記憶體在靜態區存放
  • 被類的所有物件所共享

2.4 簡單的程式碼解釋並說明如何使用

class Test {
	public int a = 10;
	public static int b = 20;
}

// 類已經載入,並沒有例項化,此時靜態區已經開闢,可以呼叫使用靜態變數,並不依賴於物件存在,而是依賴於類的存在,使用時,直接類名.變數名,即可。
syso(Test.b); // 輸出 20

// 例項化物件,此時才在堆空間中開闢一系列的記憶體,上述原理中已經闡述,此時才可以呼叫a的值。
Test t = new Test();
syso(t.a); // 輸出 10
// 當然也可呼叫 b 的值
syso(t.b); // 輸出 20

3. static修飾成員方法

3.1 為什麼使用static去修飾成員方法

用static修飾的成員變數是靜態變數,也稱類變數,它是隨著類的載入而載入的,地址記憶體在靜態區,不再依賴物件而存在。但是如何手動改變或設定或呼叫它的值呢,即操作static資料成員?

  • 可以預設初始化,即開闢記憶體空間的時候,底層自動賦予它型別預設的初始值。
  • 顯示初始化。即在定義其的時候,給它一個值。
public static int a = 10;

但是如何手動的給它賦予值並且呼叫呢,這就引入了用static修飾的成員方法,類方法。

2.2 static修飾的成員方法的特點

  • 不再是普通的成員方法,而是類方法,隨著類的載入而載入,不再依賴於物件,而是依賴於類。因
  • 為不再依賴於物件的存在,所以就和物件毫無關係,所以在類方法中不存在 this 引用(this表當前物件,隨著物件的建立而載入),所以就不能呼叫非靜態的成員變數和函式。
  • 只能訪問靜態成員和靜態的成員方法
  • 類比物件優先
  • 靜態只能訪問靜態

2.3 簡單的程式碼解釋並說明如何使用

class Test {
	// 一般的類中的成員變數都是私有的
	private static String lib;
	// static 只能訪問靜態成員 和 靜態方法
	public static String getLib() {
		// 普通資料成員,依賴物件
		
		// 不依賴物件
		// 不存在 this.lib; 不存在 this 引用
		return lib;
	}
	      // 區域性變數
	public static void setLib(String lib) {
		// 通過類名.static成員 解決同名的問題
		School.lib = lib;
		//static 不可以呼叫其它 非 static 的成員方法
	}
}

// 在使用的時候,直接 類名.方法名 即可
// 如果要使用類,必須先把 .class 檔案裝入記憶體   當裝入記憶體後,類立馬開闢記憶體在方法區,形成類的物件
		
// 類成員 呼叫方法
// 類名 .成員名
School.setLib("1");
System.out.println("lib: " + School.getLib());

3. static修飾程式碼塊

3.1 概述靜態程式碼塊

在Java中的程式碼塊,有區域性程式碼塊,構造程式碼塊,靜態程式碼塊,三者執行順序,作用,會單獨出一篇博文來簡單說明。所謂靜態程式碼塊就是用static修飾的程式碼塊。

class Test {
	// 靜態程式碼塊
	static {
		syso(...);
	}
}
  1. 靜態程式碼塊,隨著類的載入而載入,指執行一次,且優於主函式的執行,即在main函式入口之前就執行。
  2. 靜態程式碼塊是由類呼叫的,在主函式之前就執行。
  3. 作用:對類和靜態變數進行一系列的初始化
  4. 靜態程式碼塊中的變數是區域性變數,與普通函式中的區域性變數性質沒有區別。
  5. 可以由多個靜態程式碼塊

3.2 程式碼解釋

輸出:

在這裡插入圖片描述

可以明顯的看出,當類載入還未執行main函式的時候,主類中的static已經執行,之後執行main函式,從上至下順序執行,當類進行例項化的時候,同樣也是現執行類中的static程式碼塊,再執行構造器中的程式碼塊

4. 總結static關鍵字static

1.靜態方法 | 靜態成員變數:
類中的方法 | 成員變數,加上static修飾,就成了靜態成員方法(類方法) | 靜態成員變數(類變數)
2.static成員方法和普通成員方法的本質區別在於沒有this指標
static成員方法只能引用類中的靜態成員(屬性、方法)
static成員方法不能引用類中的非靜態成員
3.類變數和類方法,都是隨著類的載入而載入的,依賴於類,優於物件的,使用的時候 類名.變數名(方法名),被類的所有物件而共享的
4.普通成員方法既可以引用static成員,也可以普通成員
5.可以通過類名呼叫static成員方法,也可以通過物件名呼叫
6.static方法之所以存在,就是為了操作static資料成員

到此這篇關於java關鍵字static的使用詳解的文章就介紹到這了,更多相關java關鍵字static內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!