Java?中的靜態(tài)字段和靜態(tài)方法?
先看看下面這一串代碼:
public class Main { ? ? public static void main(String[] args) { ? ? ? ? System.out.println("Hello, WOrld!"); ? ? } }
我們的 ??main
?? 方法被標(biāo)記了 ??static
?? 修飾符,那么 ??static?? 這個修飾符的含義是啥呢?
一、靜態(tài)變量
如果一個字段定義為 static
,那么每個類只有一個這樣的字段。
先來看看沒有靜態(tài)靜態(tài)遍歷的類:
class Student { ? int stuId; ? String name; ? String school = "HY No.1 High School"; }
假設(shè)高中有 1500 名學(xué)生,上述代碼現(xiàn)在所有的實例數(shù)據(jù)成員在每次創(chuàng)建對象時都會得到內(nèi)存。
所有的學(xué)生都有其獨特的 stuId 和名字,這些實例數(shù)據(jù)成員在這種情況下是正確的,畢竟都是唯一的。
但是,這里的 "school " 是所有對象的共同屬性。如果不聲明為靜態(tài)變量的話,也會占用多個內(nèi)存。但如果我們把它變成靜態(tài)的,這個字段將只獲得一次內(nèi)存。
靜態(tài)變量聲明
class Student { ? int stuId; ?// 實例變量 ? String name; ? static String school = "HY No.1 High School"; // 靜態(tài)變量 }
如果你將任何變量聲明為靜態(tài),它就被稱為靜態(tài)變量。
- 靜態(tài)變量可以用來指代所有對象的共同屬性(對每個對象來說不是唯一的),例如,雇員的公司名稱,學(xué)生的學(xué)院名稱等。
- 靜態(tài)變量只在類加載時在類區(qū)獲得一次內(nèi)存。
靜態(tài)變量測試
代碼測試:
package com.yuzhou1su.RelearnJava; class Student { ? ? int stuId;? ? ? String name; ? ? static String school = "HY No.1 High School"; ?? ? ? Student(int id, String n) { ? ? ? ? stuId = id; ? ? ? ? name = n; ? ? } ? ? void display() { ? ? ? ? System.out.println("Student id:" + stuId + ", Name:" + name + " is from " + school); ? ? } } public class TestVariable { ? ? public static void main(String[] args) { ? ? ? ? // TODO Auto-generated method stub ? ? ? ? Student s1 = new Student(001, "Karsa"); ? ? ? ? Student s2 = new Student(002, "Ellen"); ? ? ? ? s1.display(); ? ? ? ? s2.display(); ? ? } }
執(zhí)行結(jié)果:
Student id:1, Name:Karsa is from HY No.1 High School
Student id:2, Name:Ellen is from HY No.1 High School
靜態(tài)變量只會獲得一次內(nèi)存,如果任何對象更改了靜態(tài)變量的值,它將保留其值。
看如下代碼:
package com.yuzhou1su.RelearnJava; public class StaticVariableCount { ?? ? static int count = 0; ?? ? StaticVariableCount() { ? ? count++; ? ? System.out.println(count); ? } ? public static void main(String[] args) { ? ? // TODO Auto-generated method stub ? ? StaticVariableCount svc1 = new StaticVariableCount(); ? ? StaticVariableCount svc2 = new StaticVariableCount(); ? ? StaticVariableCount svc3 = new StaticVariableCount(); ? ?? ? } }
測試結(jié)果:
1
2
3
二、靜態(tài)方法
Java中的靜態(tài)方法是一個屬于類的方法,但不被認(rèn)為是該類的實例;相反,Java中的靜態(tài)方法可以很容易地被創(chuàng)建和實現(xiàn),而不需要任何實例的調(diào)用。靜態(tài)方法可以訪問類中的任何數(shù)據(jù)成員,可以對數(shù)據(jù)成員進行任何操作,也可以將任何數(shù)值作為輸入,盡管要訪問的成員變量在類中應(yīng)該有變量的范圍,而方法只能是靜態(tài)的。
public static void syntax_ex (String_name) { ? ? Body of the program for execution. }
- public。該類的訪問修飾語是public。
- static。方法的范圍是靜態(tài)的,這意味著所有的成員變量和返回類型都在靜態(tài)的范圍內(nèi)。
- void。語法流程中的這個關(guān)鍵字表示在當(dāng)前方法中沒有處理任何返回類型。
- syntax_ex。類的名稱,表示靜態(tài)方法是當(dāng)前定義的類的一部分,后面是字符串名稱。
- body。它包括整個核心邏輯或業(yè)務(wù)邏輯(如果需要在靜態(tài)模式下)。
如果你在任何方法上使用靜態(tài)關(guān)鍵字,它就被稱為靜態(tài)方法,
靜態(tài)方法:
- 靜態(tài)方法屬于類,而不是屬于類的對象。
- 靜態(tài)方法可以被調(diào)用而不需要創(chuàng)建一個類的實例。
- 靜態(tài)方法可以訪問靜態(tài)數(shù)據(jù)成員,并可以改變它的值。
靜態(tài)方法測試
如果我們想更改學(xué)習(xí)名字的操作呢?就可以聲明一個靜態(tài)方法。
package com.yuzhou1su.RelearnJava; class Student { ? ? int stuId;? ? ? String name; ? ? static String school = "HY No.1 High School"; ? ?? ? ? static void changeSchool() { ? ? ? ? school = "HY No.5 High School"; ? ? } ?? ? ? Student(int id, String n) { ? ? ? ? stuId = id; ? ? ? ? name = n; ? ? } ? ? void display() { ? ? ? ? System.out.println("Student id:" + stuId + ", Name:" + name + " is from " + school); ? ? } } public class TestVariable { ? ? public static void main(String[] args) { ? ? ? ? // TODO Auto-generated method stub ? ? ? ?? ? ? ? ? Student.changeSchool(); ? ? ? ? Student s1 = new Student(001, "Karsa"); ? ? ? ? Student s2 = new Student(002, "Ellen"); ? ? ? ? s1.display(); ? ? ? ? s2.display(); ? ? } }
測試結(jié)果:
Student id:1, Name:Karsa is from HY No.5 High School
Student id:2, Name:Ellen is from HY No.5 High School
靜態(tài)方法是如何工作的
- 靜態(tài)方法和實例方法是 Java 中的兩種方法,它們在程序員中造成了一些混亂,但這僅僅是一種誤解。靜態(tài)方法和實例方法都有很大的區(qū)別。讓我們看看靜態(tài)方法在 Java 中是如何工作的。Java 中的靜態(tài)方法是一種駐留在類中的方法,即使沒有創(chuàng)建對象或沒有進行實例化,也可以訪問。在類的名稱后面加上方法的名稱并傳遞參數(shù),就可以訪問該類的任何實例。
- 它可以被表示為
??ClassName.methodName
(arguments)?? 。此外,這些方法的組成有一個目標(biāo),即該方法應(yīng)可與類中的所有成員變量和每個人的對象共享,其范圍由修改器 ??static?? 定義。這些方法沒有任何重載的能力;相反,它們可以在編譯時使用編譯器的靜態(tài)綁定來重載,每當(dāng)程序員需要在類的所有實例、對象或成員變量之間共享一個共同的代碼片段時,靜態(tài)方法就會成為救星,因為它通過創(chuàng)建一個共同的靜態(tài)范圍來為所有成員、對象和變量創(chuàng)造一種共享的規(guī)定。 - 一個類的所有靜態(tài)字段都可以使用靜態(tài)字段作為一個類的靜態(tài)方法的一部分進行訪問。另外,靜態(tài)方法也與內(nèi)存分配功能有關(guān),并且也是可以支持的。它將靜態(tài)方法字段和變量的一部分與一些永久生成的堆存儲在內(nèi)存中,用于關(guān)聯(lián)值。內(nèi)存分配不支持對象作為靜態(tài)方法堆的創(chuàng)建,或者方法本身不支持實例化。但接下來的問題是,靜態(tài)方法是如何通過共享和創(chuàng)建所有成員的范圍作為類的一部分來工作的。
為什么 Java Main 方法是靜態(tài)方法
這是因為對象不需要調(diào)用靜態(tài)方法。如果是非靜態(tài)方法,JVM 會先創(chuàng)建一個對象,然后調(diào)用 ??main()?? 方法,這會導(dǎo)致額外內(nèi)存分配的問題。
main 方法不對任何對象進行操作,事實上,在啟動程序時還沒有任何對象。靜態(tài)的 main 方法將執(zhí)行并構(gòu)造程序所需要的對象。
三、靜態(tài)常量
靜態(tài)變量使用的比較少,但靜態(tài)常量卻很常用。比如 Math 類中定義一個靜態(tài)常量:
public class Math { ? public static final double PI = 3.14159265358979; }
然后在程序中,可以用 Math.PI 來訪問這個常量。
四、總結(jié)
Java 中為什么需要靜態(tài)變量?
答:每當(dāng)我們希望為一個類的所有對象擁有一個公共屬性時,我們就使用一個類級別的變量,即靜態(tài)變量。
在類加載時,此變量僅在內(nèi)存中加載一次。 由于它不是在Java中按對象定義的,因此可以節(jié)省內(nèi)存。
為什么用 Java 創(chuàng)建靜態(tài)變量不是一個好習(xí)慣?
答:靜態(tài)變量是類的所有對象共有的。 如果創(chuàng)建了新對象,則無需測試靜態(tài)變量的值。 使用靜態(tài)變量的任何代碼都可以處于任何狀態(tài)。 它可以在新對象內(nèi)或在類級別。 因此,靜態(tài)變量的范圍在Java類中是開放式的。
如果我們希望對范圍進行更嚴(yán)格的控制,則變量應(yīng)在對象創(chuàng)建級別創(chuàng)建。
同樣,定義靜態(tài)變量也不是一個好習(xí)慣,因為它們違反了面向?qū)ο缶幊痰脑怼?/p>
Java 中靜態(tài)方法的目的?
答:Java 提供了靜態(tài)方法的功能來在類級別創(chuàng)建行為。 靜態(tài)方法是類的所有對象所共有的。 我們不需要創(chuàng)建類的任何對象來調(diào)用靜態(tài)方法。 因此,它提供了不創(chuàng)建用于調(diào)用它的對象的便利。
靜態(tài)方法也可以訪問和修改靜態(tài)數(shù)據(jù)成員。 這也有助于在類級別上保持行為和狀態(tài)。
為什么在 Java 中將 main 方法標(biāo)記為靜態(tài)方法?
答:Java 中的 main 方法被標(biāo)記為靜態(tài),因此 JVM 可以調(diào)用它來啟動程序。 如果 main 方法不是靜態(tài)的,那么Java進程將調(diào)用哪個構(gòu)造函數(shù)?
因此,在Java中將主要方法標(biāo)記為靜態(tài)是眾所周知的約定。 但是,如果我們?nèi)コ齭tatic,那將會有歧義。 Java進程可能不知道要調(diào)用哪個類的方法來啟動程序。
因此,此約定有助于 Java 進程識別類中作為參數(shù)傳遞給 Java 進程的程序的啟動代碼。
在什么情況下我們使用靜態(tài)塊?
答:有時,有一個具有靜態(tài)成員變量的類。 這些變量需要一些復(fù)雜的初始化。 這時,靜態(tài)塊可作為初始化復(fù)雜靜態(tài)成員變量初始化的工具。靜態(tài)塊甚至在執(zhí)行main之前執(zhí)行。有時,我們也可以用靜態(tài)的類方法替換靜態(tài)塊。
是否可以在不定義main()方法的情況下執(zhí)行程序?
答:不,從Java 7開始,您需要main()方法來執(zhí)行程序。 在Java的早期版本中,有一種解決方法可用于使用靜態(tài)塊執(zhí)行。 但是現(xiàn)在這個差距已經(jīng)縮小。
當(dāng)main方法的簽名中未提及static修飾符時會發(fā)生什么?
答:根據(jù)Java規(guī)范,main方法必須標(biāo)記為靜態(tài)。 它只需要一個字符串?dāng)?shù)組的參數(shù)即可。
程序可以使用非靜態(tài)方法進行編譯。 但是在執(zhí)行時會給出NoSuchMethodError。
Java中的靜態(tài)方法和實例方法有什么區(qū)別?
答:通常,需要為不依賴于對象成員變量的類定義行為。 這種行為是通過靜態(tài)方法捕獲的。 如果存在依賴于對象成員變量的行為,則我們不會將其標(biāo)記為靜態(tài),而是將其保留為實例方法。
要調(diào)用為靜態(tài)方法,我們不需要創(chuàng)建對象。 我們只用類名來稱呼它。 但是要調(diào)用實例方法,我們需要先創(chuàng)建/獲取一個對象。
實例成員變量不能通過靜態(tài)方法訪問。 但是實例方法可以調(diào)用實例變量和靜態(tài)變量。
到此這篇關(guān)于Java 中的靜態(tài)字段和靜態(tài)方法 的文章就介紹到這了,更多相關(guān)Java 靜態(tài)方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot中設(shè)置定時任務(wù)的三種方法小結(jié)
在我們開發(fā)項目過程中,經(jīng)常需要定時任務(wù)來幫助我們來做一些內(nèi)容,本文介紹了springboot中設(shè)置定時任務(wù)的三種方法,主要包括@Scheduled注解,Quartz框架和xxl-job框架的實現(xiàn),感興趣的可以了解一下2023-12-12MyBatis中使用#{}和${}占位符傳遞參數(shù)的各種報錯信息處理方案
這篇文章主要介紹了MyBatis中使用#{}和${}占位符傳遞參數(shù)的各種報錯信息處理方案,分別介紹了兩種占位符的區(qū)別,本文給大家介紹的非常詳細,需要的朋友可以參考下2024-01-01SpringBoot整合RedisTemplate實現(xiàn)緩存信息監(jiān)控的步驟
這篇文章主要介紹了SpringBoot整合RedisTemplate實現(xiàn)緩存信息監(jiān)控,一步一步的實現(xiàn)?Springboot?整合?Redis?來存儲數(shù)據(jù),讀取數(shù)據(jù),需要的朋友可以參考下2022-01-01Springboot jar文件如何打包zip在linux環(huán)境運行
這篇文章主要介紹了Springboot jar文件如何打包zip在linux環(huán)境運行,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-02-02Spring Boot實現(xiàn)郵件發(fā)送必會的5種姿勢
這篇文章主要給大家介紹了關(guān)于Spring Boot實現(xiàn)郵件發(fā)送必會的5種姿勢,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07