最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中的static關鍵字你了解多少

 更新時間:2022年02月08日 09:58:43   作者:Matrix海子  
這篇文章主要為大家詳細介紹了Java中的static關鍵字,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助

一.static關鍵字的用途

在《Java編程思想》P86頁有這樣一段話:

“static方法就是沒有this的方法。在static方法內部不能調用非靜態(tài)方法,反過來是可以的。而且可以在沒有創(chuàng)建任何對象的前提下,僅僅通過類本身來調用static方法。這實際上正是static方法的主要用途。”

這段話雖然只是說明了static方法的特殊之處,但是可以看出static關鍵字的基本作用,簡而言之,一句話來描述就是:

方便在沒有創(chuàng)建對象的情況下來進行調用(方法/變量)。

很顯然,被static關鍵字修飾的方法或者變量不需要依賴于對象來進行訪問,只要類被加載了,就可以通過類名去進行訪問。

static可以用來修飾類的成員方法、類的成員變量,另外可以編寫static代碼塊來優(yōu)化程序性能。

1)static方法

static方法一般稱作靜態(tài)方法,由于靜態(tài)方法不依賴于任何對象就可以進行訪問,因此對于靜態(tài)方法來說,是沒有this的,因為它不依附于任何對象,既然都沒有對象,就談不上this了。并且由于這個特性,在靜態(tài)方法中不能訪問類的非靜態(tài)成員變量和非靜態(tài)成員方法,因為非靜態(tài)成員方法/變量都是必須依賴具體的對象才能夠被調用。

但是要注意的是,雖然在靜態(tài)方法中不能訪問非靜態(tài)成員方法和非靜態(tài)成員變量,但是在非靜態(tài)成員方法中是可以訪問靜態(tài)成員方法/變量的。舉個簡單的例子:

在上面的代碼中,由于print2方法是獨立于對象存在的,可以直接用過類名調用。假如說可以在靜態(tài)方法中訪問非靜態(tài)方法/變量的話,那么如果在main方法中有下面一條語句:

MyObject.print2();

此時對象都沒有,str2根本就不存在,所以就會產生矛盾了。同樣對于方法也是一樣,由于你無法預知在print1方法中是否訪問了非靜態(tài)成員變量,所以也禁止在靜態(tài)成員方法中訪問非靜態(tài)成員方法。

而對于非靜態(tài)成員方法,它訪問靜態(tài)成員方法/變量顯然是毫無限制的。

因此,如果說想在不創(chuàng)建對象的情況下調用某個方法,就可以將這個方法設置為static。我們最常見的static方法就是main方法,至于為什么main方法必須是static的,現(xiàn)在就很清楚了。因為程序在執(zhí)行main方法的時候沒有創(chuàng)建任何對象,因此只有通過類名來訪問。

另外記住,關于構造器是否是static方法可參考:http://www.fzitv.net/article/236684.htm

2)static變量

static變量也稱作靜態(tài)變量,靜態(tài)變量和非靜態(tài)變量的區(qū)別是:靜態(tài)變量被所有的對象所共享,在內存中只有一個副本,它當且僅當在類初次加載時會被初始化。而非靜態(tài)變量是對象所擁有的,在創(chuàng)建對象的時候被初始化,存在多個副本,各個對象擁有的副本互不影響。

static成員變量的初始化順序按照定義的順序進行初始化。

3)static代碼塊

static關鍵字還有一個比較關鍵的作用就是 用來形成靜態(tài)代碼塊以優(yōu)化程序性能。static塊可以置于類中的任何地方,類中可以有多個static塊。在類初次被加載的時候,會按照static塊的順序來執(zhí)行每個static塊,并且只會執(zhí)行一次。

為什么說static塊可以用來優(yōu)化程序性能,是因為它的特性:只會在類加載的時候執(zhí)行一次。下面看個例子:

class Person{
    private Date birthDate;
    public Person(Date birthDate) {
        this.birthDate = birthDate;
    }
    boolean isBornBoomer() {
        Date startDate = Date.valueOf("1946");
        Date endDate = Date.valueOf("1964");
        return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
    }
}

isBornBoomer是用來這個人是否是1946-1964年出生的,而每次isBornBoomer被調用的時候,都會生成startDate和birthDate兩個對象,造成了空間浪費,如果改成這樣效率會更好:

class Person{
    private Date birthDate;
    private static Date startDate,endDate;
    static{
        startDate = Date.valueOf("1946");
        endDate = Date.valueOf("1964");
    }
    public Person(Date birthDate) {
        this.birthDate = birthDate;
    }
    boolean isBornBoomer() {
        return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
    }
}

因此,很多時候會將一些只需要進行一次的初始化操作都放在static代碼塊中進行。

二.static關鍵字的誤區(qū)

1.static關鍵字會改變類中成員的訪問權限嗎?

有些初學的朋友會將java中的static與C/C++中的static關鍵字的功能混淆了。在這里只需要記住一點:與C/C++中的static不同,Java中的static關鍵字不會影響到變量或者方法的作用域。在Java中能夠影響到訪問權限的只有privatepublicprotected(包括包訪問權限)這幾個關鍵字。看下面的例子就明白了:

提示錯誤"Person.age 不可視",這說明static關鍵字并不會改變變量和方法的訪問權限。

2.能通過this訪問靜態(tài)成員變量嗎?

雖然對于靜態(tài)方法來說沒有this,那么在非靜態(tài)方法中能夠通過this訪問靜態(tài)成員變量嗎?先看下面的一個例子,這段代碼輸出的結果是什么?

public class Main {  
    static int value = 33;
    public static void main(String[] args) throws Exception{
        new Main().printValue();
    }
    private void printValue(){
        int value = 3;
        System.out.println(this.value);
    }
}

33

這里面主要考察隊this和static的理解。this代表什么?this代表當前對象,那么通過new Main()來調用printValue的話,當前對象就是通過new Main()生成的對象。而static變量是被對象所享有的,因此在printValue中的this.value的值毫無疑問是33。在printValue方法內部的value是局部變量,根本不可能與this關聯(lián),所以輸出結果是33。在這里永遠要記住一點:靜態(tài)成員變量雖然獨立于對象,但是不代表不可以通過對象去訪問,所有的靜態(tài)方法和靜態(tài)變量都可以通過對象訪問(只要訪問權限足夠)。

3.static能作用于局部變量么?

在C/C++中static是可以作用域局部變量的,但是在Java中切記:static是不允許用來修飾局部變量。不要問為什么,這是Java語法的規(guī)定。

三.常見的筆試面試題

下面列舉一些面試筆試中經常遇到的關于static關鍵字的題目,僅供參考,如有補充歡迎下方留言。

1.下面這段代碼的輸出結果是什么?

public class Test extends Base{
    static{
        System.out.println("test static");
    }
    public Test(){
        System.out.println("test constructor");
    }
    public static void main(String[] args) {
        new Test();
    }
}
class Base{
    static{
        System.out.println("base static");
    }
    public Base(){
        System.out.println("base constructor");
    }
}

base static
test static
base constructor
test constructor

至于為什么是這個結果,我們先不討論,先來想一下這段代碼具體的執(zhí)行過程,在執(zhí)行開始,先要尋找到main方法,因為main方法是程序的入口,但是在執(zhí)行main方法之前,必須先加載Test類,而在加載Test類的時候發(fā)現(xiàn)Test類繼承自Base類,因此會轉去先加載Base類,在加載Base類的時候,發(fā)現(xiàn)有static塊,便執(zhí)行了static塊。在Base類加載完成之后,便繼續(xù)加載Test類,然后發(fā)現(xiàn)Test類中也有static塊,便執(zhí)行static塊。在加載完所需的類之后,便開始執(zhí)行main方法。在main方法中執(zhí)行new Test()的時候會先調用父類的構造器,然后再調用自身的構造器。因此,便出現(xiàn)了上面的輸出結果。

2.這段代碼的輸出結果是什么?

public class Test {
    Person person = new Person("Test");
    static{
        System.out.println("test static");
    }
    public Test() {
        System.out.println("test constructor");
    }
    public static void main(String[] args) {
        new MyClass();
    }
}
class Person{
    static{
        System.out.println("person static");
    }
    public Person(String str) {
        System.out.println("person "+str);
    }
}
class MyClass extends Test {
    Person person = new Person("MyClass");
    static{
        System.out.println("myclass static");
    }
    public MyClass() {
        System.out.println("myclass constructor");
    }
}

test static
myclass static
person static
person Test
test constructor
person MyClass
myclass constructor

類似地,我們還是來想一下這段代碼的具體執(zhí)行過程。首先加載Test類,因此會執(zhí)行Test類中的static塊。接著執(zhí)行new MyClass(),而MyClass類還沒有被加載,因此需要加載MyClass類。在加載MyClass類的時候,發(fā)現(xiàn)MyClass類繼承自Test類,但是由于Test類已經被加載了,所以只需要加載MyClass類,那么就會執(zhí)行MyClass類的中的static塊。在加載完之后,就通過構造器來生成對象。而在生成對象的時候,必須先初始化父類的成員變量,因此會執(zhí)行Test中的Person person = new Person(),而Person類還沒有被加載過,因此會先加載Person類并執(zhí)行Person類中的static塊,接著執(zhí)行父類的構造器,完成了父類的初始化,然后就來初始化自身了,因此會接著執(zhí)行MyClass中的Person person = new Person(),最后執(zhí)行MyClass的構造器。

3.這段代碼的輸出結果是什么?

public class Test {
    static{
        System.out.println("test static 1");
    }
    public static void main(String[] args) {
         
    }
    static{
        System.out.println("test static 2");
    }
}

test static 1
test static 2

雖然在main方法中沒有任何語句,但是還是會輸出,原因上面已經講述過了。另外,static塊可以出現(xiàn)類中的任何地方(只要不是方法內部,記住,任何方法內部都不行),并且執(zhí)行是按照static塊的順序執(zhí)行的。

總結

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內容!     

相關文章

  • java實現(xiàn)的AES秘鑰生成算法示例

    java實現(xiàn)的AES秘鑰生成算法示例

    這篇文章主要介紹了java實現(xiàn)的AES秘鑰生成算法,結合實例形式分析了AES秘鑰生成算法原理與實現(xiàn)技巧,需要的朋友可以參考下
    2017-01-01
  • Java中對null進行強制類型轉換的方法

    Java中對null進行強制類型轉換的方法

    小編對null進行強轉會不會拋錯,非常的好奇,下面小編通過實例代碼給大家介紹Java中對null進行強制類型轉換的方法,感興趣的朋友參考下吧
    2018-09-09
  • Spring Cloud負載均衡及遠程調用實現(xiàn)詳解

    Spring Cloud負載均衡及遠程調用實現(xiàn)詳解

    這篇文章主要介紹了Spring Cloud負載均衡及遠程調用實現(xiàn)詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08
  • Java解決約瑟夫問題代碼實例

    Java解決約瑟夫問題代碼實例

    這篇文章主要介紹了Java解決約瑟夫(環(huán))問題的代碼實例,決約瑟問題貌似經常出現(xiàn)在面試題中,需要的朋友可以參考下
    2014-03-03
  • Spring-Security對HTTP相應頭的安全支持方式

    Spring-Security對HTTP相應頭的安全支持方式

    這篇文章主要介紹了Spring-Security對HTTP相應頭的安全支持方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • springcloud安裝rabbitmq并配置延遲隊列插件的過程詳解

    springcloud安裝rabbitmq并配置延遲隊列插件的過程詳解

    本期主要講解如何利用docker快速安裝rabbitmq并且配置延遲隊列插件,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • Java8 CompletableFuture詳解

    Java8 CompletableFuture詳解

    這篇文章主要介紹了Java8 CompletableFuture詳解,CompletableFuture extends Future提供了方法,一元操作符和促進異步性以及事件驅動編程模型,需要的朋友可以參考下
    2014-06-06
  • restTemplate未設置連接數(shù)導致服務雪崩問題以及解決

    restTemplate未設置連接數(shù)導致服務雪崩問題以及解決

    面對線上問題,仔細分析原因,及時調整配置,能有效解決問題,本文詳細描述了線上遇到流量突增引發(fā)的問題,通過查看代碼和連接池信息,分析出問題的原因是連接池滿了,連接池大小配置不足以應對大并發(fā)流量,通過調整連接池大小配置
    2024-10-10
  • Mybatis查詢條件包含List的情況說明

    Mybatis查詢條件包含List的情況說明

    這篇文章主要介紹了Mybatis 查詢條件包含List的情況,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • maven 刪除下載失敗的包的方法

    maven 刪除下載失敗的包的方法

    本文介紹了當Maven包報紅時,使用刪除相關文件的方法來解決該問題,具有一定的參考價值,感興趣的可以了解一下
    2023-09-09

最新評論

罗甸县| 南投县| 磐石市| 峨眉山市| 扎鲁特旗| 云浮市| 汉寿县| 尤溪县| 霍林郭勒市| 滨州市| 巴彦县| 固阳县| 三河市| 施甸县| 浪卡子县| 定日县| 文安县| 射洪县| 金湖县| 藁城市| 灵山县| 嘉兴市| 连南| 防城港市| 义乌市| 同心县| 潜山县| 蒲江县| 左云县| 陆河县| 客服| 祁门县| 洪雅县| 舒兰市| 恩施市| 永登县| 太湖县| 祁阳县| 镇远县| 天津市| 海盐县|