static关键字_聊聊static关键字
? ? ? ? ?前言:今天看看powermock測試框架的基礎知識,簡單了解了一下Mock?的底層原理。
? ? ? ? ?Mockito底層使用了動態代理,用到了CGLIB。因此需要被mock的對象,Mockito都會生成一個子類繼承該類,代理的對象會代替真實的對象進行執行。子類會覆蓋父類。而static 修飾的方法不能被覆蓋(也就是不能被重寫)。這也就是為什么final修飾的類,private 方法。static 方法不可以被Mock的原因。
? ? ? ? ?靜態方法可以被繼承不能被重寫
一、static?關鍵字的使用
? ? ? ?static屬于java當中的一個關鍵字,可以用來修飾變量、方法、類和代碼塊。
static用來修飾變量,表示這個變量是一個靜態變量,屬于類變量,可以直接通過類名.變量名調用
static用來修飾方法,表示這個方法是一個靜態方法,也可以直接通過類名.方法名來調用
static用來修飾類,注意,這個類只能是靜態內部類。你想想,static修飾的變量和方法都是直屬于類的,不用創建對象就可以使用,如果在外部類上加上static修飾,這不就矛盾了嗎。靜態內部類不依附于外部類,可以將他當做一個普通的類來使用
static修飾代碼塊,稱為靜態代碼塊。使用靜態代碼塊包裹的部分會在類加載的時候就會被執行,一般使用靜態代碼塊來加載資源
二、類加載
? ??我們都知道靜態方法中不能調用非靜態的方法和變量。那么這是什么原因呢,這就涉及到類加載的一個過程了
類加載的過程
加載:獲取類的二進制字節流,將其靜態存儲結構轉化為方法區運行時的數據
校驗:確保class文件的字節流包含的信息符合當前虛擬機的要求
準備:為類變量,靜態方法分配內存
解析:將類型中的引用轉化為直接引用
初始化:非靜態的成員賦值
使用:
卸載:
? ? ? 了解了類加載的過程,就明白了為什么靜態方法中不能直接調用非靜態的變量和方法。因為靜態變量和方法在準備階段就會被創建和分配內存,非靜態的方法和變量在初始化階段才被創建。在靜態方法里面調用的非靜態方法和屬性都還沒有被創建出來,所以不能調用
三、static存放的位置
?JVM內存模型
程序計數器:記錄當前線程執行到那一條字節碼指令。多線程環境下,線程分別利用CPU資源,有時候當前線程操作還沒有執行完,就別其他線程搶占了CPU資源,這個時候程序計數器就會記錄當前線程執行到的位置,方便下次線程搶占到CPU資源時,還從上回斷開的位置繼續
虛擬機棧:每個方法被執行的時候,都會在虛擬機棧上開辟一小塊的內存區域,這部分區域叫做棧幀。我們通常所說的遞歸調用會出現壓棧,指的就是這個虛擬機棧。虛擬機棧上還存放有對象的引用
本地方法棧:存放本地方法(java中使用native關鍵字修飾的方法)的局部變量表
堆:存儲對象本身
方法區:存放常量、所有類的信息,靜態變量,靜態方法,普通方法
使用staitc修飾的靜態變量和靜態方法,存儲在方法區中的靜態區
四、staitc變量初始化問題
?咱們先來看一道題目,請忽視代碼不規范的問題,一個類中不應該寫多個class的,但這里僅用于測試
/** * 測試static 變量初始化 */public class TestStatic { public static void main(String[] args) { SingleTon singleTon = SingleTon.getInstance(); System.out.println("count1=" + singleTon.count1); System.out.println("count2=" + singleTon.count2); }}class SingleTon { private static SingleTon singleTon = new SingleTon(); public static int count1; public static int count2 = 1; private SingleTon() { count1++; count2++; } public static SingleTon getInstance() { return singleTon; }}? ? 剛看到這個題目,我脫口而出,count1=1,count2=2。結果被打臉了,看看運行結果。
為什么會這樣?
這是因為使用static修飾的變量和方法,它們的初始化是按照代碼中的順序來的。它會先執行SingleTon singleTon = new SingleTon();并且將count1和count2初始化為0。先執行count1++和count2++后,才會執行count2=1的賦值操作。
換種寫法,將位置互換一下
public class TestStatic2 { public static void main(String[] args) { SingleTon2 singleTon = SingleTon2.getInstance(); System.out.println("count1=" + singleTon.count1); System.out.println("count2=" + singleTon.count2); }}class SingleTon2 { public static int count1; public static int count2 = 1; private static SingleTon2 singleTon = new SingleTon2(); private SingleTon2() { count1++; count2++; } public static SingleTon2 getInstance() { return singleTon; }}? ? ?這才是我們想的那種情況
五、static修飾的變量和方法能否被繼承
? ? 直接代碼演示
/** * Author: 徐志 * Date: 2020/7/11 10:24 * 測試static修飾的變量能否被繼承 */public class TestStatic3 { public static void main(String[] args) { B b=new B(); B.a(); System.out.println(B.a); }}class A{ public static int a=5; //靜態變量 public static void a(){ System.out.println("我是A類中的靜態方法"); } public void b(){ }}class B extends A{}我們發現,靜態變量和方法是可以被繼承的
那么它能不能被重寫呢?我們修改一下代碼
/** * Author: 徐志 * Date: 2020/7/11 10:24 * 測試static修飾的變量能否被繼承 */public class TestStatic3 { public static void main(String[] args) { A b=new B(); b.a(); System.out.println(B.a); }}class A{ public static int a=5; //靜態變量 public static void a(){ System.out.println("我是A類中的靜態方法"); } public void b(){ }}class B extends A{ public static void a(){ System.out.println("這是B類中的靜態方法"); }}? ?運行結果
結果沒變,我們發現它其實是不能被重寫的。其實idea是十分智能的,我在在使用快捷鍵的時候,發現根本沒有重寫a()方法的選項,不然的話重寫后的a方法是會有一個@Override的注解標識的
還記得多態調用要滿足的條件嗎?
1.子類和父類存在繼承關系
2.子類重寫父類中的方法
3.父類引用指向子類對象
總結
以上是生活随笔為你收集整理的static关键字_聊聊static关键字的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于stm32智能风扇_一款基于STM3
- 下一篇: python语言的类型是_Python语