欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Java編程中static關(guān)鍵字和final關(guān)鍵字的使用

 更新時(shí)間:2015年09月27日 09:00:26   投稿:goldensun  
這篇文章主要介紹了詳解Java編程中static關(guān)鍵字和final關(guān)鍵字的使用,是Java入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下

Java static關(guān)鍵字以及Java靜態(tài)變量和靜態(tài)方法
static 修飾符能夠與變量、方法一起使用,表示是“靜態(tài)”的。

靜態(tài)變量和靜態(tài)方法能夠通過類名來訪問,不需要?jiǎng)?chuàng)建一個(gè)類的對象來訪問該類的靜態(tài)成員,所以static修飾的成員又稱作類變量和類方法。靜態(tài)變量與實(shí)例變量不同,實(shí)例變量總是通過對象來訪問,因?yàn)樗鼈兊闹翟趯ο蠛蛯ο笾g有所不同。

請看下面的例子:

public class Demo {
  static int i = 10;
  int j;
  Demo() {
    this.j = 20;
  }
  public static void main(String[] args) {
    System.out.println("類變量 i=" + Demo.i);
    Demo obj = new Demo();
    System.out.println("實(shí)例變量 j=" + obj.j);
  }
}

運(yùn)行結(jié)果:

類變量 i=10
實(shí)例變量 j=20


static 的內(nèi)存分配

靜態(tài)變量屬于類,不屬于任何獨(dú)立的對象,所以無需創(chuàng)建類的實(shí)例就可以訪問靜態(tài)變量。之所以會(huì)產(chǎn)生這樣的結(jié)果,是因?yàn)榫幾g器只為整個(gè)類創(chuàng)建了一個(gè)靜態(tài)變量的副本,也就是只分配一個(gè)內(nèi)存空間,雖然有多個(gè)實(shí)例,但這些實(shí)例共享該內(nèi)存。實(shí)例變量則不同,每創(chuàng)建一個(gè)對象,都會(huì)分配一次內(nèi)存空間,不同變量的內(nèi)存相互獨(dú)立,互不影響,改變 a 對象的實(shí)例變量不會(huì)影響 b 對象。

請看下面的代碼:

public class Demo {
  static int i;
  int j;
  public static void main(String[] args) {
    Demo obj1 = new Demo();
    obj1.i = 10;
    obj1.j = 20;
    
    Demo obj2 = new Demo();
    
    System.out.println("obj1.i=" + obj1.i + ", obj1.j=" + obj1.j);
    System.out.println("obj2.i=" + obj2.i + ", obj2.j=" + obj2.j);
  }
}

運(yùn)行結(jié)果:

obj1.i=10, obj1.j=20
obj2.i=10, obj2.j=0

注意:靜態(tài)變量雖然也可以通過對象來訪問,但是不被提倡,編譯器也會(huì)產(chǎn)生警告。

上面的代碼中,i 是靜態(tài)變量,通過 obj1 改變 i 的值,會(huì)影響到 obj2;j 是實(shí)例變量,通過 obj1 改變 j 的值,不會(huì)影響到 obj2。這是因?yàn)?obj1.i 和 obj2.i 指向同一個(gè)內(nèi)存空間,而 obj1.j 和 obj2.j 指向不同的內(nèi)存空間,請看下圖:

注意:static 的變量是在類裝載的時(shí)候就會(huì)被初始化。也就是說,只要類被裝載,不管你是否使用了這個(gè)static 變量,它都會(huì)被初始化。

小結(jié):類變量(class variables)用關(guān)鍵字 static 修飾,在類加載的時(shí)候,分配類變量的內(nèi)存,以后再生成類的實(shí)例對象時(shí),將共享這塊內(nèi)存(類變量),任何一個(gè)對象對類變量的修改,都會(huì)影響其它對象。外部有兩種訪問方式:通過對象來訪問或通過類名來訪問。
靜態(tài)方法

靜態(tài)方法是一種不能向?qū)ο髮?shí)施操作的方法。例如,Math 類的 pow() 方法就是一個(gè)靜態(tài)方法,語法為 Math.pow(x, a),用來計(jì)算 x 的 a 次冪,在使用時(shí)無需創(chuàng)建任何 Math 對象。

因?yàn)殪o態(tài)方法不能操作對象,所以不能在靜態(tài)方法中訪問實(shí)例變量,只能訪問自身類的靜態(tài)變量。

以下情形可以使用靜態(tài)方法:
一個(gè)方法不需要訪問對象狀態(tài),其所需參數(shù)都是通過顯式參數(shù)提供(例如 Math.pow())。
一個(gè)方法只需要訪問類的靜態(tài)變量。

讀者肯定注意到,main() 也是一個(gè)靜態(tài)方法,不對任何對象進(jìn)行操作。實(shí)際上,在程序啟動(dòng)時(shí)還沒有任何對象,main() 方法是程序的入口,將被執(zhí)行并創(chuàng)建程序所需的對象。

關(guān)于靜態(tài)變量和靜態(tài)方法的總結(jié):
一個(gè)類的靜態(tài)方法只能訪問靜態(tài)變量;
一個(gè)類的靜態(tài)方法不能夠直接調(diào)用非靜態(tài)方法;
如訪問控制權(quán)限允許,靜態(tài)變量和靜態(tài)方法也可以通過對象來訪問,但是不被推薦;
靜態(tài)方法中不存在當(dāng)前對象,因而不能使用 this,當(dāng)然也不能使用 super;
靜態(tài)方法不能被非靜態(tài)方法覆蓋;
構(gòu)造方法不允許聲明為 static 的;
局部變量不能使用static修飾。

靜態(tài)方法舉例:

public class Demo {
  static int sum(int x, int y){
    return x + y;
  }
  public static void main(String[] args) {
    int sum = Demo.sum(10, 10);
    System.out.println("10+10=" + sum);
  }
}

運(yùn)行結(jié)果:

10+10=20

static 方法不需它所屬的類的任何實(shí)例就會(huì)被調(diào)用,因此沒有 this 值,不能訪問實(shí)例變量,否則會(huì)引起編譯錯(cuò)誤。

注意:實(shí)例變量只能通過對象來訪問,不能通過類訪問。
靜態(tài)初始器(靜態(tài)塊)

塊是由大括號包圍的一段代碼。靜態(tài)初始器(Static Initializer)是一個(gè)存在于類中、方法外面的靜態(tài)塊。靜態(tài)初始器僅僅在類裝載的時(shí)候(第一次使用類的時(shí)候)執(zhí)行一次,往往用來初始化靜態(tài)變量。

示例代碼:

public class Demo {
  public static int i;
  static{
    i = 10;
    System.out.println("Now in static block.");
  }
  public void test() {
    System.out.println("test method: i=" + i);
  }
  public static void main(String[] args) {
    System.out.println("Demo.i=" + Demo.i);
    new Demo().test();
  }
}

運(yùn)行結(jié)果是:

Now in static block.
Demo.i=10
test method: i=10


靜態(tài)導(dǎo)入

靜態(tài)導(dǎo)入是 Java 5 的新增特性,用來導(dǎo)入類的靜態(tài)變量和靜態(tài)方法。

一般我們導(dǎo)入類都這樣寫:

import packageName.className; // 導(dǎo)入某個(gè)特定的類




import packageName.*; // 導(dǎo)入包中的所有類

而靜態(tài)導(dǎo)入可以這樣寫:

import static packageName.className.methonName; // 導(dǎo)入某個(gè)特定的靜態(tài)方法



import static packageName.className.*; // 導(dǎo)入類中的所有靜態(tài)成員

導(dǎo)入后,可以在當(dāng)前類中直接用方法名調(diào)用靜態(tài)方法,不必再用 className.methodName 來訪問。

對于使用頻繁的靜態(tài)變量和靜態(tài)方法,可以將其靜態(tài)導(dǎo)入。靜態(tài)導(dǎo)入的好處是可以簡化一些操作,例如輸出語句 System.out.println(); 中的 out 就是 System 類的靜態(tài)變量,可以通過 import static java.lang.System.*; 將其導(dǎo)入,下次直接調(diào)用 out.println() 就可以了。

請看下面的代碼:

import static java.lang.System.*;
import static java.lang.Math.random;
public class Demo {
  public static void main(String[] args) {
    out.println("產(chǎn)生的一個(gè)隨機(jī)數(shù):" + random());
  }
}

運(yùn)行結(jié)果:

產(chǎn)生的一個(gè)隨機(jī)數(shù):0.05800891549018705

Java final關(guān)鍵字:阻止繼承和多態(tài)
在 Java 中,聲明類、變量和方法時(shí),可使用關(guān)鍵字 final 來修飾。final 所修飾的數(shù)據(jù)具有“終態(tài)”的特征,表示“最終的”意思。具體規(guī)定如下:
final 修飾的類不能被繼承。
final 修飾的方法不能被子類重寫。
final 修飾的變量(成員變量或局部變量)即成為常量,只能賦值一次。
final 修飾的成員變量必須在聲明的同時(shí)賦值,如果在聲明的時(shí)候沒有賦值,那么只有 一次賦值的機(jī)會(huì),而且只能在構(gòu)造方法中顯式賦值,然后才能使用。
final 修飾的局部變量可以只聲明不賦值,然后再進(jìn)行一次性的賦值。

final 一般用于修飾那些通用性的功能、實(shí)現(xiàn)方式或取值不能隨意被改變的數(shù)據(jù),以避免被誤用,例如實(shí)現(xiàn)數(shù)學(xué)三角方法、冪運(yùn)算等功能的方法,以及數(shù)學(xué)常量π=3.141593、e=2.71828 等。

事實(shí)上,為確保終態(tài)性,提供了上述方法和常量的 java.lang.Math 類也已被定義為final 的。

需要注意的是,如果將引用類型(任何類的類型)的變量標(biāo)記為 final,那么該變量不能指向任何其它對象。但可以改變對象的內(nèi)容,因?yàn)橹挥幸帽旧硎?final 的。

如果變量被標(biāo)記為 final,其結(jié)果是使它成為常數(shù)。想改變 final 變量的值會(huì)導(dǎo)致一個(gè)編譯錯(cuò)誤。下面是一個(gè)正確定義 final 變量的例子:

public final int MAX_ARRAY_SIZE = 25; // 常量名一般大寫


常量因?yàn)橛?final 修飾,所以不能被繼承。

請看下面的代碼:

public final class Demo{
  public static final int TOTAL_NUMBER = 5;
  public int id;
  public Demo() {
    // 非法,對final變量TOTAL_NUMBER進(jìn)行二次賦值了
    // 因?yàn)?+TOTAL_NUMBER相當(dāng)于 TOTAL_NUMBER=TOTAL_NUMBER+1
    id = ++TOTAL_NUMBER;
  }
  public static void main(String[] args) {
    final Demo t = new Demo();
    final int i = 10;
    final int j;
    j = 20;
    j = 30; // 非法,對final變量進(jìn)行二次賦值
  }
}

final 也可以用來修飾類(放在 class 關(guān)鍵字前面),阻止該類再派生出子類,例如 Java.lang.String 就是一個(gè) final 類。這樣做是出于安全原因,因?yàn)橐WC一旦有字符串的引用,就必須是類 String 的字符串,而不是某個(gè)其它類的字符串(String 類可能被惡意繼承并篡改)。

方法也可以被 final 修飾,被 final 修飾的方法不能被覆蓋;變量也可以被 final 修飾,被 final 修飾的變量在創(chuàng)建對象以后就不允許改變它們的值了。一旦將一個(gè)類聲明為 final,那么該類包含的方法也將被隱式地聲明為 final,但是變量不是。

被 final 修飾的方法為靜態(tài)綁定,不會(huì)產(chǎn)生多態(tài)(動(dòng)態(tài)綁定),程序在運(yùn)行時(shí)不需要再檢索方法表,能夠提高代碼的執(zhí)行效率。在Java中,被 static 或 private 修飾的方法會(huì)被隱式的聲明為 final,因?yàn)閯?dòng)態(tài)綁定沒有意義。

由于動(dòng)態(tài)綁定會(huì)消耗資源并且很多時(shí)候沒有必要,所以有一些程序員認(rèn)為:除非有足夠的理由使用多態(tài)性,否則應(yīng)該將所有的方法都用 final 修飾。

這樣的認(rèn)識(shí)未免有些偏激,因?yàn)?JVM 中的即時(shí)編譯器能夠?qū)崟r(shí)監(jiān)控程序的運(yùn)行信息,可以準(zhǔn)確的知道類之間的繼承關(guān)系。如果一個(gè)方法沒有被覆蓋并且很短,編譯器就能夠?qū)λM(jìn)行優(yōu)化處理,這個(gè)過程為稱為內(nèi)聯(lián)(inlining)。例如,內(nèi)聯(lián)調(diào)用 e.getName() 將被替換為訪問 e.name 變量。這是一項(xiàng)很有意義的改進(jìn),這是由于CPU在處理調(diào)用方法的指令時(shí),使用的分支轉(zhuǎn)移會(huì)擾亂預(yù)取指令的策略,所以,這被視為不受歡迎的。然而,如果 getName() 在另外一個(gè)類中被覆蓋,那么編譯器就無法知道覆蓋的代碼將會(huì)做什么操作,因此也就不能對它進(jìn)行內(nèi)聯(lián)處理了。

相關(guān)文章

  • Java之int數(shù)組聲明與初始化方式

    Java之int數(shù)組聲明與初始化方式

    這篇文章主要介紹了Java之int數(shù)組聲明與初始化方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 解決SpringMVC使用@RequestBody注解報(bào)400錯(cuò)誤的問題

    解決SpringMVC使用@RequestBody注解報(bào)400錯(cuò)誤的問題

    這篇文章主要介紹了解決SpringMVC使用@RequestBody注解報(bào)400錯(cuò)誤的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Quarkus集成open api接口使用swagger ui展示

    Quarkus集成open api接口使用swagger ui展示

    這篇文章主要為大家介紹了Quarkus集成open?api接口使用swagger?ui的展示示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-02-02
  • JAVA使用JDBC技術(shù)操作SqlServer數(shù)據(jù)庫實(shí)例代碼

    JAVA使用JDBC技術(shù)操作SqlServer數(shù)據(jù)庫實(shí)例代碼

    本篇文章主要介紹了JAVA使用JDBC技術(shù)操作SqlServer數(shù)據(jù)庫實(shí)例代碼,具有一定的參考價(jià)值,有興趣的可以了解一下。
    2017-01-01
  • SpringBoot之使用Redis實(shí)現(xiàn)分布式鎖(秒殺系統(tǒng))

    SpringBoot之使用Redis實(shí)現(xiàn)分布式鎖(秒殺系統(tǒng))

    這篇文章主要介紹了SpringBoot之使用Redis實(shí)現(xiàn)分布式鎖(秒殺系統(tǒng)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Spring集成事務(wù)代碼實(shí)例

    Spring集成事務(wù)代碼實(shí)例

    這篇文章主要介紹了Spring集成事務(wù)代碼實(shí)例,pring事務(wù)的本質(zhì)其實(shí)就是數(shù)據(jù)庫對事務(wù)的支持,使用JDBC的事務(wù)管理機(jī)制,就是利用java.sql.Connection對象完成對事務(wù)的提交,需要的朋友可以參考下
    2023-10-10
  • Springboot配置security basic path無效解決方案

    Springboot配置security basic path無效解決方案

    這篇文章主要介紹了Springboot配置security basic path無效解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • SpringBoot發(fā)送短信驗(yàn)證碼的實(shí)例

    SpringBoot發(fā)送短信驗(yàn)證碼的實(shí)例

    第三方短信發(fā)送平臺(tái)有很多種,各個(gè)平臺(tái)有各自的優(yōu)缺點(diǎn),在選擇的時(shí)候可以根據(jù)自己的具體實(shí)際情況定奪,本文主要介紹了SpringBoot發(fā)送短信驗(yàn)證碼的實(shí)例,感興趣的可以了解一下
    2022-02-02
  • logback-spring.xml的配置及示例詳解(直接復(fù)制粘貼可用)

    logback-spring.xml的配置及示例詳解(直接復(fù)制粘貼可用)

    在使用logback作為日志框架時(shí),可以創(chuàng)建一個(gè)名為logback-spring.xml的配置文件來自定義日志輸出的格式和方式,下面這篇文章主要給大家介紹了關(guān)于logback-spring.xml的配置及示例詳解的相關(guān)資料,文中的代碼直接復(fù)制粘貼可用,需要的朋友可以參考下
    2024-01-01
  • interrupt()和線程終止方式_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    interrupt()和線程終止方式_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    線程的thread.interrupt()方法是中斷線程,將會(huì)設(shè)置該線程的中斷狀態(tài)位,即設(shè)置為true,中斷的結(jié)果線程是死亡、還是等待新的任務(wù)或是繼續(xù)運(yùn)行至下一步,就取決于這個(gè)程序本身
    2017-05-05

最新評論