夯實Java基礎(七)——Static關鍵字

来源:https://www.cnblogs.com/tang-hao-/archive/2019/07/22/11220387.html
-Advertisement-
Play Games

1、static介紹 static關鍵字一直是各大企業中面試常常會問到的問題,主要考察面試者的基礎是否扎實,下麵來介紹一下static關鍵字。 Java中static表示“全局”或者“靜態”的意思,可以用來修飾成員變數、成員方法、代碼塊、內部類和導包。在Java中並不存在全局變數的概念,但是我們可以 ...


1、static介紹

static關鍵字一直是各大企業中面試常常會問到的問題,主要考察面試者的基礎是否扎實,下麵來介紹一下static關鍵字。

Java中static表示“全局”或者“靜態”的意思,可以用來修飾成員變數、成員方法、代碼塊、內部類和導包。在Java中並不存在全局變數的概念,但是我們可以通過static來實現一個“偽全局”的概念,被static修飾的成員變數和成員方法獨立於該類的任何對象。也就是說,它不依賴類特定的實例,被類的所有實例共用。只要這個類被載入了,Java虛擬機就能根據類名在運行時數據區的方法區內定找到他們。因此,static對象可以在它的任何對象創建之前訪問,無需引用任何對象,所以被static修飾的成員變數和成員方法可以直接使用類名調用。

class Person{
    private static int num=0;

    public Person() {
        num++;
    }

    public static void plus(){
        System.out.println(Person.num);
    }

    public static void main(String[] args) {
        new Person();
        new Person();
        Person.plus();
        plus();
    }
}
//結果:2、2

2、static變數

static修飾的成員變數稱作靜態變數,靜態變數被所有的對象所共用,在記憶體中只有一個,它會隨著類的載入而載入。

另外主要:static是不允許用來修飾局部變數

提到靜態變數我們來看靜態變數和非靜態變數的區別:

靜態變數(類變數):靜態變數被所有的對象所共用,也就是說我們創建了一個類的多個對象,多個對象共用著一個靜態變數,如果我們修改了靜態變數的值,那麼其他對象的靜態變數也會隨之修改。

非靜態變數(實例變數):如果我們創建了一個類的多個對象,那麼每個對象都有它自己該有的非靜態變數。當你修改其中一個對象中的非靜態變數時,不會引起其他對象非靜態變數值得改變。

class Person{
    private static int num;
    private int num1;

    public static void main(String[] args) {
        Person p1 = new Person();
        Person p2 = new Person();

        Person.num=10;
        p1.num1=11;

        Person.num=100;
        p2.num1=111;

        System.out.println(Person.num);
        System.out.println(p1.num);
        System.out.println(p2.num);
        System.out.println(p1.num1);
        System.out.println(p2.num1);
    }
}

從運行結果來看,static變數的值是相同的,說明是共用的,而非靜態變數他們的值則不相同,說明依賴於實例。雖然static修飾的變數它不依賴類特定的實例,但它畢竟也是類中的一個屬性,也是可以通過類的實例來調用的,只不過屬性的值是共用的而已。但是最好還是用類名調用

3、static方法

static修飾的成員方法稱作靜態方法,這樣我們就可以通過“類名. 方法名”進行調用。由於靜態方法在類載入的時候就存在了,所以它不依賴於任何對象的實例就可以進行調用,因此對於靜態方法而言,是木有當前對象的概念,即沒有this、super關鍵字的。因為static方法獨立於任何實例,因此static方法必須被實現,而不能是抽象的abstract。

並且由於獨立於任何實例,在靜態方法中不能訪問類的非靜態成員變數和非靜態成員方法,因為非靜態成員方法/變數都是必須依賴具體的對象才能夠被調用。但是要註意的是,雖然在靜態方法中不能訪問非靜態成員方法和非靜態成員變數,但是在非靜態成員方法中是可以訪問靜態成員方法/變數的。舉個簡單的例子:

class Person{

    public static void main(String[] args) {
        Person p=new Person();
        p.show1();
    }

    public void show1(){
        System.out.println("非靜態方法show1()...");
        show2();
        show3();
    }

    public static void show2(){
        System.out.println("靜態方法show2()...");
        //這裡編譯會報錯Non-static method 'show1()' cannot be referenced from a static context
        //show1();
    }
    public static void show3(){
        System.out.println("靜態方法show3()...");
        show2();
    }
}

4、static代碼塊

被static修飾的代碼塊也叫靜態代碼塊,會隨著JVM載入類的時候而載入這些靜態代碼塊,並且會自動執行它們可以有多個,可以存在於該類的任何地方。JVM會按照它們的先後順序依次執行它們,而且每個靜態代碼塊只會被初始化一次,不會進行多次初始化。

示例:

public class Person{

    static {
        System.out.println("Person類靜態塊");
    }

    public Person() {
        System.out.println("Person類構造器");
    }

    public static void main(String[] args) {
        new Son();
        System.out.println("-------");
        new Son();
    }
}

class Son extends Person{
    static {
        System.out.println("Son類靜態塊");
    }

    public Son() {
        System.out.println("Son類構造器");
    }
}

運行結果:

從運行結果分析:首先運行main()方法,然後JVM就會載入類,因為Son類繼承了Person類,所以會先載入父類Person類,再去載入子類Son。由於靜態代碼塊會隨著類的載入而載入,所以先輸出父類中靜態代碼塊內容"Person類靜態塊",然後輸出子類中靜態代碼塊內容"Son類靜態塊"。載入完類之後執行main()方法內容,先new了第一個Son實例,由於子類構造器中預設調用了super(),所以先輸出父類構造器的內容,再輸出子類構造器的內容。之後又new了第二個Son實例,卻是輸出的構造器的內容,說明static靜態塊只載入了一次。結論:靜態代碼塊是先載入父類的靜態代碼塊,然後再載入子類靜態代碼塊,是隨著類的載入而載入,而且只會載入一次。

補充:因為入口main()是個方法,也需要用類去調用,所以類的載入優先順序>main()方法。

5、static內部類

static修飾內部類的用法很少,畢竟內部類用的就不是很多,一般在源碼中才能看見。但是就是有這麼一個特殊的用法是用static修飾內部類。普通類是不允許聲明為靜態的,只要內部類才可以,被static修飾的內部類可以直接作為一個普通類來使用,而不需先實例一個外部類。

static修飾內部類註意幾點:

  • 靜態內部類只能訪問外部類的靜態成員,否則編譯會報錯。
  • 不管是靜態方法還是非靜態方法都可以在非靜態內部類中訪問。
  • 如果需要調用內部類的非靜態方法,必須先new一個OuterClass的對象outerClass,然後通過outer。new生成內部類的對象,而static內部類則不需要。

簡單舉例:

public class OuterClass {
    private static int num=6;
    // 靜態內部類
    public static class InnerStaticClass{
        public void print() {
            System.out.println("靜態內部類方法print()=="+num);
        }
    }
    //非靜態內部類
    public class InnerClass{

        public void display(){
            System.out.println("非靜態內部類方法display()=="+num);
            show();
        }
    }
    public void show(){
        System.out.println("外部類的show()方法=="+num);
    }

    public static void main(String[] args) {
        //非static對象實例
        OuterClass outer = new OuterClass();
        OuterClass.InnerClass innerClass = outer.new InnerClass();
        innerClass.display();
        //static對象實例
        OuterClass.InnerStaticClass staticClass=new OuterClass.InnerStaticClass();
        staticClass.print();
    }
}

6、static導包

這個知識點非常的冷門,基本上很少的地方會用,我們只需要瞭解一下即可,用static修飾導包的格式是 import static  包名,static不能寫在import前面,這樣可以指定導入某個類中的指定靜態資源,並且不需要使用類名.資源名,可以直接使用資源名。

來看一下案例:

import static java.lang.Math.*;

public class StaticTest {
    public static void main(String[] args) {
        System.out.println(sqrt(9));
        System.out.println(abs(-12));
    }
}
//結果:3、12

從上面的案例看出,使用import static我們導入了Math類下的所有靜態資,所以我們就可以直接使用sqrt(9)、abs(-12)靜態方法了。

這樣在寫代碼的時候確實能省一點代碼,但是會影響代碼可讀性,所以一般情況下不建議這麼使用。

7、總結

static是非常重要的一個關鍵字,它的用法也很豐富,以下總結為:

①、static可以用來修飾成員變數、成員方法、代碼塊、內部類和導包。

②、用來修飾成員變數,將其變為靜態變數,從而實現所有對象對於該成員的共用,通過“類名.變數名”即可調用。

③、用來修飾成員方法,將其變為靜態方法,可以直接使用“類名.方法名”的方式調用,常用於工具類。

④、靜態方法中不能使用關鍵字this和super 。

⑤、靜態塊用法,將多個類成員放在一起初始化,使得程式更加規整,其中理解對象的初始化過程非常關鍵。

⑥、靜態代碼塊是先載入父類的靜態代碼塊,然後再載入子類靜態代碼塊,而且只會載入一次。

⑦、static修飾成員變數、成員方法、代碼塊會隨著類的載入而載入。

⑧、靜態導包用法,將類的方法直接導入到當前類中,從而直接使用“方法名”即可調用類方法,更加方便,但是代碼的可讀性降低。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、什麼是容器 1、容器是一種輕量級、可移植、自包含的軟體打包技術,使應用程式可以在幾乎任何地方以相同的方式運行。開發人員在自己的筆記本上創建並測試好的容器,無需任何修改就能夠在生產系統的虛擬機、或物理伺服器、或公有雲主機上運行。 2、容器與虛擬機的異同: 容器與虛擬機都是為應用提供封裝和隔離。 容 ...
  • 黑馬2017年java就業班全套視頻教程 ava學習路線圖.pptx等多個文件 ava學習路線圖.pptx等多個文件 - 2019-07-20 10:03 老師分享的資料 老師分享的資料 - 2019-07-20 10:03 面試相關資料 面試相關資料 - 2019-07-20 10:03 java ...
  • python全套視頻,第十五期,從入門到精通,基礎班,就業班,面試,軟體包 下載地址 ...
  • 一、變數 1.註意點: 在同一個“作用域”中,變數名不能重名,但是變數可以重新賦值。 2.什麼是作用域? 答:描述的是變數的有效範圍,在範圍之內是可以被訪問的,只要出了作用域就無法訪問(也就是在大括弧裡面才行) 3.關於變數的分類 (1)局部變數:在方法體中聲明的變數; (2)成員變數:在方法體外聲 ...
  •   Class文件是一組以8位位元組為基礎單位的二進位流,各個數據項目嚴格按照順序緊湊排列在Class文件中,中間沒有添加任何分隔符,這使得整個Class文件中存儲的內容幾乎全部是程式運行的必要數據,沒有空隙。當遇到需要占用8位位元組以上的數據項時,會按照高位在前的方式分割成若幹個8 ...
  • 註意: HttpServletRequest 請求中的 body 內容僅能調用 request.getInputStream(), request.getReader()和request.getParameter("key") 方法讀取一次,重覆讀取會報 java.io.IOException: S ...
  • 第八章 複雜搜索 黑夜給了我黑色的眼睛,我卻用它尋找光明。 經過瞭解簡單的API和簡單搜索,已經基本上能應付大部分的使用場景。可是非關係型資料庫數據的文檔數據往往又多又雜,各種各樣冗餘的欄位,組成了一條"記錄"。複雜的數據結構,帶來的就是複雜的搜索。所以在進入本章節前,我們要構建一個儘可能"複雜"的 ...
  • https://www.runoob.com/w3cnote/cpp-vector-container-analysis.html ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...