Java超詳細(xì)透徹講解static
1. 引入
當(dāng)我們編寫(xiě)一個(gè)類(lèi)時(shí),其實(shí)就是在描述其對(duì)象的屬性和行為,而并沒(méi)有產(chǎn)生實(shí)質(zhì)上的對(duì)象, 只有通過(guò)new關(guān)鍵字才會(huì)產(chǎn)生出對(duì)象,這時(shí)系統(tǒng)才會(huì)分配內(nèi)存空間給對(duì)象,其方法才可以供外部調(diào)用。我們有時(shí)候希望無(wú)論是否產(chǎn)生了對(duì)象或無(wú)論產(chǎn)生了多少對(duì)象的情況下,某些特定的數(shù)據(jù)在內(nèi)存空間里只有一份。
例如所有的中國(guó)人都有個(gè)國(guó)家名稱(chēng),每一個(gè)中國(guó)人都共享這個(gè)國(guó)家名稱(chēng),不必在每一個(gè)中國(guó)人的實(shí)例對(duì)象中都單獨(dú)分配一個(gè)用于代表國(guó)家名稱(chēng)的變量。
2. 理解
static
:靜態(tài)的
3. 使用
3.1 使用范圍
在Java類(lèi)中,可用static
修飾屬性、方法、代碼塊、內(nèi)部類(lèi)
3.2 static修飾屬性
3.2.1 設(shè)計(jì)思想
類(lèi)屬性作為該類(lèi)各個(gè)對(duì)象之間共享的變量。在設(shè)計(jì)類(lèi)時(shí),分析哪些屬性不因?qū)ο蟮牟煌淖?,將這些屬性設(shè)置為類(lèi)屬性。相應(yīng)的方法設(shè)置為類(lèi)方法。
3.2.2 分類(lèi)
屬性,按是否使用static
修飾,又分為:
靜態(tài)屬性(靜態(tài)變量或類(lèi)變量)vs 非靜態(tài)屬性(實(shí)例變量)
實(shí)例變量:我們創(chuàng)建了類(lèi)的多個(gè)對(duì)象,每個(gè)對(duì)象都獨(dú)立的擁有一套類(lèi)中的非靜態(tài)屬性。當(dāng)修改其中一個(gè)對(duì)象中的非靜態(tài)屬性時(shí),不會(huì)導(dǎo)致其他對(duì)象中同樣的屬性值的修改。
靜態(tài)變量:我們創(chuàng)建了類(lèi)的多個(gè)對(duì)象,多個(gè)對(duì)象共享同一個(gè)靜態(tài)變量。當(dāng)通過(guò)某一個(gè)對(duì)象修改靜態(tài)變量時(shí),會(huì)導(dǎo)致其他對(duì)象調(diào)用此靜態(tài)變量時(shí),是修改過(guò)了的。
3.2.3 注意
靜態(tài)變量隨著類(lèi)的加載而加載??梢酝ㄟ^(guò)"類(lèi).靜態(tài)變量"的方式進(jìn)行調(diào)用。
靜態(tài)變量的加載要早于對(duì)象的創(chuàng)建。
修飾的成員,被所有對(duì)象所共享。
訪(fǎng)問(wèn)權(quán)限允許時(shí),可不創(chuàng)建對(duì)象,直接被類(lèi)調(diào)用。
由于類(lèi)只會(huì)加載一次,則靜態(tài)變量在內(nèi)存中也只會(huì)存在一份:存在方法區(qū)的靜態(tài)域中。
無(wú)論創(chuàng)建多少個(gè)對(duì)象,靜態(tài)數(shù)據(jù)都只占用一份存儲(chǔ)區(qū)域。
static
關(guān)鍵字不能應(yīng)用于局部變量, 因此它只能作用于域。
① 如果一個(gè)域是靜態(tài)的基本類(lèi)型域,且也沒(méi)有對(duì)它進(jìn)行初始化,那么它就會(huì)獲得基本類(lèi)型的標(biāo)準(zhǔn)初值。
② 如果它是一個(gè)對(duì)象引用,那么它的默認(rèn)初始化值就是null
。
靜態(tài)變量與實(shí)例變量可修飾的范圍區(qū)別:
靜態(tài)變量 | 實(shí)例變量 | |
---|---|---|
類(lèi) | yes | no |
對(duì)象 | yes | yes |
3.2.4 舉例
靜態(tài)屬性舉例: ① System.out;
② Math.PI;
應(yīng)用舉例:
應(yīng)用舉例1:
public class Test1 { public static void main(String args[]) { Circle c1 = new Circle(2.0); Circle c2 = new Circle(3.0); c1.display();//name:這是一個(gè)圓radius:2.0 c2.display();//name:這是一個(gè)圓radius:3.0 } } class Circle { private double radius; public static String name = "這是一個(gè)圓"; public static String getName() { return name; } public Circle(double radius) { this.radius = radius; } public double findArea() { return Math.PI * radius * radius; } public void display() { System.out.println("name:" + name + "radius:" + radius); } }
應(yīng)用舉例2:
class Person { private int id; public static int total = 0; public Person() { total++; id = total; } public static void main(String args[]){ Person Tom=new Person(); Tom.id=0; total=100; // 不用創(chuàng)建對(duì)象就可以訪(fǎng)問(wèn)靜態(tài)成員 } }
應(yīng)用舉例3:
public class StaticDemo { public static void main(String args[]) { Person.total = 100; // 不用創(chuàng)建對(duì)象就可以訪(fǎng)問(wèn)靜態(tài)成員 //訪(fǎng)問(wèn)方式:類(lèi)名.類(lèi)屬性,類(lèi)名.類(lèi)方法 System.out.println(Person.total); Person c = new Person(); System.out.println(c.total); //101 } }
3.2.5 類(lèi)變量?jī)?nèi)存解析
圖解1:
圖解2:
3.3 static修飾方法
3.3.1 設(shè)計(jì)思想
如果方法與調(diào)用者無(wú)關(guān),則這樣的方法通常被聲明為類(lèi)方法,由 于不需要?jiǎng)?chuàng)建對(duì)象就可以調(diào)用類(lèi)方法,從而簡(jiǎn)化了方法的調(diào)用。
3.3.2 理解
static
修飾方法為靜態(tài)方法。
3.3.3 使用
沒(méi)有對(duì)象的實(shí)例時(shí),可以用類(lèi)名.方法名()
的形式訪(fǎng)問(wèn)由static
修飾的類(lèi)方法。
靜態(tài)方法與非靜態(tài)方法可修飾的范圍區(qū)別:
靜態(tài)方法 | 非靜態(tài)方法 | |
---|---|---|
類(lèi) | yes | no |
對(duì)象 | yes | yes |
3.3.4 注意
因?yàn)椴恍枰獙?shí)例就可以訪(fǎng)問(wèn)static
方法,因此static
方法內(nèi)部不能有this
。(也不能有super
)
static
修飾的方法不能被重寫(xiě)。
靜態(tài)方法中,只能調(diào)用靜態(tài)的方法或?qū)傩浴?/p>
非靜態(tài)方法中,既可以調(diào)用非靜態(tài)的方法或?qū)傩?,也可以調(diào)用靜態(tài)的方法或?qū)傩浴?/p>
3.3.5 舉例
public class StaticTest { public static void main(String[] args) { Chinese.nation = "中國(guó)"; Chinese c1 = new Chinese(); c1.name = "姚明"; c1.age = 40; c1.nation = "CHN"; Chinese c2 = new Chinese(); c2.name = "馬龍"; c2.age = 30; c2.nation = "CHINA"; System.out.println(c1.nation);//CHINA //編譯不通過(guò) // Chinese.name = "張繼科"; c1.eat(); Chinese.show(); //編譯不通過(guò) // Chinese.eat(); // Chinese.info(); } } //中國(guó)人 class Chinese{ String name; int age; static String nation; public void eat(){ System.out.println("中國(guó)人吃中餐"); //調(diào)用非靜態(tài)結(jié)構(gòu) this.info(); System.out.println("name :" +name); //調(diào)用靜態(tài)結(jié)構(gòu) walk(); System.out.println("nation : " + nation); } public static void show(){ System.out.println("我是一個(gè)中國(guó)人!"); //不能調(diào)用非靜態(tài)的結(jié)構(gòu) // eat(); // name = "Tom"; //可以調(diào)用靜態(tài)的結(jié)構(gòu) System.out.println(Chinese.nation); walk(); } public void info(){ System.out.println("name :" + name +",age : " + age); } public static void walk(){ } }
4. 注意
關(guān)于靜態(tài)屬性和靜態(tài)方法的使用,可都從生命周期的角度去理解。
開(kāi)發(fā)中,如何確定一個(gè)屬性是否要聲明為static
的?
屬性是可以被多個(gè)對(duì)象所共享的,不會(huì)隨著對(duì)象的不同而不同的。
類(lèi)中的常量也常常聲明為static
。
開(kāi)發(fā)中,如何確定一個(gè)方法是否要聲明為static
的?
操作靜態(tài)屬性的方法,通常設(shè)置為static
的。
工具類(lèi)中的方法,習(xí)慣上聲明為static
的。 比如:Math
、Arrays
、Collections
。
5. 單例 (Singleton)設(shè)計(jì)模式
5.1 概述
設(shè)計(jì)模式是在大量的實(shí)踐中總結(jié)和理論化之后優(yōu)選的代碼結(jié)構(gòu)、編程風(fēng)格、 以及解決問(wèn)題的思考方式。設(shè)計(jì)模免去我們自己再思考和摸索。就像是經(jīng)典的棋譜,不同的棋局,我們用不同的棋譜。”套路”
所謂類(lèi)的單例設(shè)計(jì)模式,就是采取一定的方法保證在整個(gè)的軟件系統(tǒng)中,對(duì)某個(gè)類(lèi)只能存在一個(gè)對(duì)象實(shí)例,并且該類(lèi)只提供一個(gè)取得其對(duì)象實(shí)例的方法。 如果我們要讓類(lèi)在一個(gè)虛擬機(jī)中只能產(chǎn)生一個(gè)對(duì)象,我們應(yīng)該怎么做呢?
① 我們首先必須將類(lèi)的構(gòu)造器的訪(fǎng)問(wèn)權(quán)限設(shè)置為private
這樣,就不能用new
操作符在類(lèi)的外部產(chǎn)生類(lèi)的對(duì)象了,但在類(lèi)內(nèi)部仍可以產(chǎn)生該類(lèi)的對(duì)象。
② 其次,指向類(lèi)內(nèi)部產(chǎn)生的該類(lèi)對(duì)象的變量也必須定義成靜態(tài)的
因?yàn)樵陬?lèi)的外部開(kāi)始還無(wú)法得到類(lèi)的對(duì)象,只能調(diào)用該類(lèi)的某個(gè)靜態(tài)方法以返回類(lèi)內(nèi)部創(chuàng)建的對(duì)象, 靜態(tài)方法只能訪(fǎng)問(wèn)類(lèi)中的靜態(tài)成員變量,所以,指向類(lèi)內(nèi)部產(chǎn)生的該類(lèi)對(duì)象的變量也必須定義成靜態(tài)的。
5.2 優(yōu)點(diǎn)
由于單例模式只生成一個(gè)實(shí)例,減少了系統(tǒng)性能開(kāi)銷(xiāo),當(dāng)一個(gè)對(duì)象的產(chǎn)生需要比較多的資源時(shí),如讀取配置、產(chǎn)生其他依賴(lài)對(duì)象時(shí),則可以通過(guò)在應(yīng)用啟動(dòng)時(shí)直接產(chǎn)生一個(gè)單例對(duì)象,然后永久駐留內(nèi)存的方式來(lái)解決。
5.3 單例設(shè)計(jì)模式-餓漢式
class Singleton { // 1.私有化構(gòu)造器 private Singleton() { } // 2.內(nèi)部提供一個(gè)當(dāng)前類(lèi)的實(shí)例 // 4.此實(shí)例也必須靜態(tài)化 private static Singleton single = new Singleton(); // 3.提供公共的靜態(tài)的方法,返回當(dāng)前類(lèi)的對(duì)象 public static Singleton getInstance() { return single; } }
5.4 單例設(shè)計(jì)模式-懶漢式
(1)單例設(shè)計(jì)模式-懶漢式(線(xiàn)程不安全)
class Singleton { // 1.私有化構(gòu)造器 private Singleton() { } // 2.內(nèi)部提供一個(gè)當(dāng)前類(lèi)的實(shí)例 // 4.此實(shí)例也必須靜態(tài)化 private static Singleton single; // 3.提供公共的靜態(tài)的方法,返回當(dāng)前類(lèi)的對(duì)象 public static Singleton getInstance() { if(single == null) { single = new Singleton(); } return single; } }
(2)單例設(shè)計(jì)模式-懶漢式(線(xiàn)程安全)
public class BankTest { } class Bank{ private Bank(){} private static Bank instance = null; public static Bank getInstance(){ //方式一:效率稍差 // synchronized (Bank.class) { // if(instance == null){ // // instance = new Bank(); // } // return instance; // } //方式二:效率更高 if(instance == null){ synchronized (Bank.class) { if(instance == null){ instance = new Bank(); } } } return instance; } }
5.5 應(yīng)用場(chǎng)景
網(wǎng)站的計(jì)數(shù)器,一般也是單例模式實(shí)現(xiàn),否則難以同步。
應(yīng)用程序的日志應(yīng)用,一般都使用單例模式實(shí)現(xiàn),這一般是由于共享的日志文件一直處于打開(kāi)狀態(tài),因?yàn)橹荒苡幸粋€(gè)實(shí)例去操作,否則內(nèi)容不好追加。
數(shù)據(jù)庫(kù)連接池的設(shè)計(jì)一般也是采用單例模式,因?yàn)閿?shù)據(jù)庫(kù)連接是一種數(shù)據(jù)庫(kù)資源。
項(xiàng)目中,讀取配置文件的類(lèi),一般也只有一個(gè)對(duì)象。沒(méi)有必要每次使用配置 文件數(shù)據(jù),都生成一個(gè)對(duì)象去讀取。
Application
也是單例的典型應(yīng)用。
Windows
的Task Manager
(任務(wù)管理器)就是很典型的單例模式。
Windows
的RecycleBin
(回收站)也是典型的單例應(yīng)用。在整個(gè)系統(tǒng)運(yùn)行過(guò)程中,回收站一直維護(hù)著僅有的一個(gè)實(shí)例。
到此這篇關(guān)于Java超詳細(xì)透徹講解static的文章就介紹到這了,更多相關(guān)Java static內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java連接Sql數(shù)據(jù)庫(kù)經(jīng)常用到的操作
這篇文章主要介紹了Java連接Sql數(shù)據(jù)庫(kù)經(jīng)常用到的操作的相關(guān)資料,需要的朋友可以參考下2016-02-02Mybatis查詢(xún)數(shù)據(jù)的項(xiàng)目實(shí)現(xiàn)
MyBatis通過(guò)XML配置文件或注解,把Java對(duì)象映射到對(duì)應(yīng)的數(shù)據(jù)庫(kù)表中,實(shí)現(xiàn)對(duì)象關(guān)系和數(shù)據(jù)關(guān)系的互相轉(zhuǎn)換,從而使得Java應(yīng)用程序能夠更簡(jiǎn)單的操作和讀取數(shù)據(jù)庫(kù),本文就詳細(xì)的介紹一下如何實(shí)現(xiàn),感興趣的可以了解一下2023-09-09Java發(fā)送https請(qǐng)求并跳過(guò)ssl證書(shū)驗(yàn)證方法
最近在負(fù)責(zé)一個(gè)對(duì)接第三方服務(wù)的事情,在對(duì)接期間因?yàn)榈谌椒?wù)為https的請(qǐng)求,這篇文章主要給大家介紹了關(guān)于Java發(fā)送https請(qǐng)求并跳過(guò)ssl證書(shū)驗(yàn)證的相關(guān)資料,需要的朋友可以參考下2023-11-11Spring根據(jù)URL參數(shù)進(jìn)行路由的方法詳解
這篇文章主要給大家介紹了關(guān)于Spring根據(jù)URL參數(shù)進(jìn)行路由的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起來(lái)看看吧。2017-12-12Scala 操作Redis使用連接池工具類(lèi)RedisUtil
這篇文章主要介紹了Scala 操作Redis使用連接池工具類(lèi)RedisUtil,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06java的if else語(yǔ)句入門(mén)指南(推薦)
下面小編就為大家?guī)?lái)一篇java的if else語(yǔ)句入門(mén)指南(推薦)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-06-06java多線(xiàn)程實(shí)現(xiàn)下載圖片并壓縮
這篇文章主要為大家詳細(xì)介紹了java多線(xiàn)程實(shí)現(xiàn)下載圖片并壓縮,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05