日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java 关键字—— static 与 final

發布時間:2023/12/9 java 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 关键字—— static 与 final 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? static表示“全局”或者“靜態”的意思,用來修飾成員變量和成員方法,也可以形成靜態static代碼塊,但是Java語言中沒有全局變量的概念。

? ? ? ? 被static修飾的成員變量和成員方法獨立于該類的任何對象。也就是說,它不依賴類特定的實例,被類的所有實例共享。只要這個類被加載,Java虛擬機就能根據類名在運行時數據區的方法區內定找到他們。因此,static對象可以在它的任何對象創建之前訪問,無需引用任何對象

? ? ?

? ? ? ?用public修飾的static成員變量和成員方法本質是全局變量和全局方法,當聲明它類的對象時,不生成static變量的副本,而是類的所有實例共享同一個static變量

? ? ? ?static變量前可以有private修飾,表示這個變量可以在類的靜態代碼塊中,或者類的其他靜態成員方法中使用(當然也可以在非靜態成員方法中使用),但是不能在其他類中通過類名來直接引用,這一點很重要。實際上你需要搞明白,private是訪問權限限定,static表示不要實例化就可以使用,這樣就容易理解多了。static前面加上其它訪問權限關鍵字的效果也以此類推。

? ? ?

? ? ? ?static修飾的成員變量和成員方法習慣上稱為靜態變量和靜態方法,可以直接通過類名來訪問,訪問語法為:

類名.靜態方法名(參數列表...)?

類名.靜態變量名

? ? ? ?用static修飾的代碼塊表示靜態代碼塊,當Java虛擬機(JVM)加載類時,就會執行該代碼塊。


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

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

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

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

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

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


一、static關鍵字的用途

1、static變量

? ? ? ? 按照是否靜態的對類成員變量進行分類可分兩種:一種是被static修飾的變量,叫靜態變量或類變量;另一種是沒有被static修飾的變量,叫實例變量。兩者的區別是:

? ? ? ? 對于靜態變量在內存中只有一次拷貝(節省內存),JVM只為靜態分配一次內存,在加載類的過程中完成靜態變量的內存分配,可用類名直接訪問(方便),當然也可以通過對象來訪問(但是這是不推薦的)。

? ? ? ? 對于實例變量,沒創建一個實例,就會為實例變量分配一次內存,實例變量可以在內存中有多個拷貝,互不影響(靈活)。


2、static方法

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

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


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

? ? ? ? MyObject.print2();

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

? ? ? ? 而對于非靜態成員方法,它訪問靜態成員方法/變量顯然是毫無限制的

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

? ? ? ?另外記住,即使沒有顯示地聲明為static,類的構造器實際上也是靜態方法


3、static代碼塊

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

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

[java]?view plaincopy
  • 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兩個對象,造成了空間浪費,如果改成這樣效率會更好:

    [java]?view plaincopy
  • 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關鍵字的誤區

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

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


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


    2、能通過this訪問靜態成員變量嗎?

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

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


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

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


    三、final 關鍵字的使用

    ? ? ? ? 根據程序上下文環境,Java關鍵字final有“這是無法改變的”或者“終態的”含義,它可以修飾非抽象類、非抽象類成員方法和變量。你可能出于兩種理解而需要阻止改變:設計或效率。

    final類不能被繼承,沒有子類,final類中的方法默認是final的。
    final方法不能被子類的方法覆蓋,但可以被繼承。
    final成員變量表示常量,只能被賦值一次,賦值后值不再改變。
    final不能用于修飾構造方法。

    注意:父類的private成員方法是不能被子類方法覆蓋的,因此private類型的方法默認是final類型的。


    1、final類

    ? ? ? ?final類不能被繼承,因此final類的成員方法沒有機會被覆蓋,默認都是final的。在設計類時候,如果這個類不需要有子類,類的實現細節不允許改變,并且確信這個類不會載被擴展,那么就設計為final類。


    2、final方法

    如果一個類不允許其子類覆蓋某個方法,則可以把這個方法聲明為final方法。

    使用final方法的原因有二:

    第一、把方法鎖定,防止任何繼承類修改它的意義和實現。
    第二、高效。編譯器在遇到調用final方法時候會轉入內嵌機制,大大提高執行效率。

    例如:

    [java]?view plaincopy
  • public?class?Test1?{???
  • public?static?void?main(String[]?args)?{???
  • ????//?TODO?自動生成方法存根???
  • }???
  • public?void?f1()?{???
  • ????System.out.println("f1");???
  • }???
  • //無法被子類覆蓋的方法???
  • public?final?void?f2()?{???
  • ????System.out.println("f2");???
  • }???
  • public?void?f3()?{???
  • ????System.out.println("f3");???
  • }???
  • private?void?f4()?{???
  • ????System.out.println("f4");???
  • }???
  • }???
  • public?class?Test2?extends?Test1?{???
  • ??????
  • public?void?f1(){???????
  • ????System.out.println("Test1父類方法f1被覆蓋!");???
  • }???
  • public?static?void?main(String[]?args)?{???
  • ????Test2?t=new?Test2();???
  • ????t.f1();??????
  • ????t.f2();?//調用從父類繼承過來的final方法???
  • ????t.f3();?//調用從父類繼承過來的方法???
  • ????//t.f4();?//調用失敗,無法從父類繼承獲得???
  • }???
  • }??

  • 3、final變量(常量)

    用final修飾的成員變量表示常量,值一旦給定就無法改變!

    final修飾的變量有三種:靜態變量、實例變量和局部變量,分別表示三種類型的常量。

    從下面的例子中可以看出,一旦給final變量初值后,值就不能再改變了。

    另外,final變量定義的時候,可以先聲明,而不給初值,這中變量也稱為final空白,無論什么情況,編譯器都確保空白final在使用之前必須被初始化。但是,final空白在final關鍵字final的使用上提供了更大的靈活性,為此,一個類中的final數據成員就可以實現依對象而有所不同,卻有保持其恒定不變的特征。

    [java]?view plaincopy
  • public?class?Test3?{???
  • ????????private?final?String?S?=?"final實例變量S";???
  • ????????private?final?int?A?=?100;???
  • ????????public?final?int?B?=?90;???
  • ??
  • ????????public?static?final?int?C?=?80;???
  • ????????private?static?final?int?D?=?70;???
  • ??
  • ????????public?final?int?E;?//final空白,必須在初始化對象的時候賦初值???
  • ??
  • ????????public?Test3(int?x)?{???
  • ????????????????E?=?x;???
  • ????????}???
  • ??
  • ????????/**??
  • ?????????*?@param?args??
  • ?????????*/???
  • ????????public?static?void?main(String[]?args)?{???
  • ????????????????Test3?t?=?new?Test3(2);???
  • ????????????????//t.A=101;????//出錯,final變量的值一旦給定就無法改變???
  • ????????????????//t.B=91;?//出錯,final變量的值一旦給定就無法改變???
  • ????????????????//t.C=81;?//出錯,final變量的值一旦給定就無法改變???
  • ????????????????//t.D=71;?//出錯,final變量的值一旦給定就無法改變???
  • ??
  • ????????????????System.out.println(t.A);???
  • ????????????????System.out.println(t.B);???
  • ????????????????System.out.println(t.C);?//不推薦用對象方式訪問靜態字段???
  • ????????????????System.out.println(t.D);?//不推薦用對象方式訪問靜態字段???
  • ????????????????System.out.println(Test3.C);???
  • ????????????????System.out.println(Test3.D);???
  • ????????????????//System.out.println(Test3.E);?//出錯,因為E為final空白,依據不同對象值有所不同.???
  • ????????????????System.out.println(t.E);???
  • ??
  • ????????????????Test3?t1?=?new?Test3(3);???
  • ????????????????System.out.println(t1.E);?//final空白變量E依據對象的不同而不同???
  • ????????}???
  • ??
  • ????????private?void?test()?{???
  • ????????????????System.out.println(new?Test3(1).A);???
  • ????????????????System.out.println(Test3.C);???
  • ????????????????System.out.println(Test3.D);???
  • ????????}???
  • ??
  • ????????public?void?test2()?{???
  • ????????????????final?int?a;?????//final空白,在需要的時候才賦值???
  • ????????????????final?int?b?=?4;????//局部常量--final用于局部變量的情形???
  • ????????????????final?int?c;????//final空白,一直沒有給賦值.??????
  • ????????????????a?=?3;???
  • ????????????????//a=4;????出錯,已經給賦過值了.???
  • ????????????????//b=2;?出錯,已經給賦過值了.???
  • ????????}???
  • }??

  • 4、final參數

    ? ? ? ?當函數參數為final類型時,你可以讀取使用該參數,但是無法改變該參數的值。

    [java]?view plaincopy
  • public?class?Test4?{???
  • ????????public?static?void?main(String[]?args)?{???
  • ????????????????new?Test4().f1(2);???
  • ????????}???
  • ??
  • ????????public?void?f1(final?int?i)?{???
  • ????????????????//i++;????//i是final類型的,值不允許改變的.???
  • ????????????????System.out.print(i);???
  • ????????}???
  • } ?
  • 總結

    以上是生活随笔為你收集整理的Java 关键字—— static 与 final的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。