亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

解析Java中的static關(guān)鍵字

瀏覽:3日期:2022-08-10 15:35:12
目錄一.static關(guān)鍵字使用場(chǎng)景1.1、靜態(tài)變量1.2、靜態(tài)方法1.3、靜態(tài)代碼塊1.4、靜態(tài)內(nèi)部類(lèi)1.5、靜態(tài)導(dǎo)入二.static變量和普通成員變量區(qū)別三.類(lèi)的構(gòu)造器到底是不是static方法?一.static關(guān)鍵字使用場(chǎng)景

static關(guān)鍵字主要有以下5個(gè)使用場(chǎng)景:

1.1、靜態(tài)變量

把一個(gè)變量聲明為靜態(tài)變量通常基于以下三個(gè)目的:

作為共享變量使用 減少對(duì)象的創(chuàng)建 保留唯一副本

第一種比較容易理解,由于static變量在內(nèi)存中只會(huì)存在一個(gè)副本,所以其可以作為共享變量使用,比如要定義一個(gè)全局配置、進(jìn)行全局計(jì)數(shù)。如:

public class CarConstants {// 全局配置,一般全局配置會(huì)和final一起配合使用, 作為共享變量public static final int MAX_CAR_NUM = 10000; } public class CarFactory {// 計(jì)數(shù)器private static int createCarNum = 0; public static Car createCar() { if (createCarNum > CarConstants.MAX_CAR_NUM) {throw new RuntimeException('超出最大可生產(chǎn)數(shù)量'); } Car c = new Car(); createCarNum++; return c; } public static getCreateCarNum() { return createCarNum; }}

第二種雖然場(chǎng)景不多,但是基本在每個(gè)工程里面都會(huì)使用到,比如聲明Loggger變量:

private static final Logger LOGGER = LogFactory.getLoggger(MyClass.class);

實(shí)際上,如果把static去掉也是可行的,比如:

private final Logger LOGGER = LogFactory.getLoggger(MyClass.class);

這樣一來(lái),對(duì)于每個(gè)MyClass的實(shí)例化對(duì)象都會(huì)擁有一個(gè)LOGGER,如果創(chuàng)建了1000個(gè)MyClass對(duì)象,則會(huì)多出1000個(gè)Logger對(duì)象,造成資源的浪費(fèi),因此通常會(huì)將Logger對(duì)象聲明為static變量,這樣一來(lái),能夠減少對(duì)內(nèi)存資源的占用。

第三種最經(jīng)典的場(chǎng)景莫過(guò)于單例模式了,單例模式由于必須全局只保留一個(gè)副本,所以天然和static的初衷是吻合的,用static來(lái)修飾再合適不過(guò)了。

public class Singleton { private static volatile Singleton singleton; private Singleton() {} public static Singleton getInstance() {if (singleton == null) { synchronized (Singleton.class) {if (singleton == null) { singleton = new Singleton();} }}return singleton; }}1.2、靜態(tài)方法

將一個(gè)方法聲明為靜態(tài)方法,通常是為了方便在不創(chuàng)建對(duì)象的情況下調(diào)用。這種使用方式非常地常見(jiàn),比如jdk的Collections類(lèi)中的一些方法、單例模式的getInstance方法、工廠模式的create/build方法、util工具類(lèi)中的方法。

1.3、靜態(tài)代碼塊

靜態(tài)代碼塊通常來(lái)說(shuō)是為了對(duì)靜態(tài)變量進(jìn)行一些初始化操作,比如單例模式、定義枚舉類(lèi):

單例模式

public class Singleton { private static Singleton instance; static {instance = new Singleton(); } private Singleton() {} public static Singleton getInstance() {return instance; }}

枚舉類(lèi)

public enum WeekDayEnum { MONDAY(1,'周一'), TUESDAY(2, '周二'), WEDNESDAY(3, '周三'), THURSDAY(4, '周四'), FRIDAY(5, '周五'), SATURDAY(6, '周六'), SUNDAY(7, '周日'); private int code; private String desc; WeekDayEnum(int code, String desc) {this.code = code;this.desc = desc; } private static final Map<Integer, WeekDayEnum> WEEK_ENUM_MAP = new HashMap<Integer, WeekDayEnum>(); // 對(duì)map進(jìn)行初始化 static {for (WeekDayEnum weekDay : WeekDayEnum.values()) { WEEK_ENUM_MAP.put(weekDay.getCode(), weekDay);} } public static WeekDayEnum findByCode(int code) {return WEEK_ENUM_MAP.get(code); } public int getCode() {return code; } public void setCode(int code) {this.code = code; } public String getDesc() {return desc; } public void setDesc(String desc) {this.desc = desc; }} 1.4、靜態(tài)內(nèi)部類(lèi)

內(nèi)部類(lèi)一般情況下使用不是特別多,如果需要在外部類(lèi)里面定義一個(gè)內(nèi)部類(lèi),通常是基于外部類(lèi)和內(nèi)部類(lèi)有很強(qiáng)關(guān)聯(lián)的前提下才去這么使用。

在說(shuō)靜態(tài)內(nèi)部類(lèi)的使用場(chǎng)景之前,我們先來(lái)看一下靜態(tài)內(nèi)部類(lèi)和非靜態(tài)內(nèi)部類(lèi)的區(qū)別:

非靜態(tài)內(nèi)部類(lèi)對(duì)象持有外部類(lèi)對(duì)象的引用(編譯器會(huì)隱式地將外部類(lèi)對(duì)象的引用作為內(nèi)部類(lèi)的構(gòu)造器參數(shù));而靜態(tài)內(nèi)部類(lèi)對(duì)象不會(huì)持有外部類(lèi)對(duì)象的引用

由于非靜態(tài)內(nèi)部類(lèi)的實(shí)例創(chuàng)建需要有外部類(lèi)對(duì)象的引用,所以非靜態(tài)內(nèi)部類(lèi)對(duì)象的創(chuàng)建必須依托于外部類(lèi)的實(shí)例;而靜態(tài)內(nèi)部類(lèi)的實(shí)例創(chuàng)建只需依托外部類(lèi);

并且由于非靜態(tài)內(nèi)部類(lèi)對(duì)象持有了外部類(lèi)對(duì)象的引用,因此非靜態(tài)內(nèi)部類(lèi)可以訪問(wèn)外部類(lèi)的非靜態(tài)成員;而靜態(tài)內(nèi)部類(lèi)只能訪問(wèn)外部類(lèi)的靜態(tài)成員;

兩者的根本性區(qū)別其實(shí)也決定了用static去修飾內(nèi)部類(lèi)的真正意圖:

內(nèi)部類(lèi)需要脫離外部類(lèi)對(duì)象來(lái)創(chuàng)建實(shí)例 避免內(nèi)部類(lèi)使用過(guò)程中出現(xiàn)內(nèi)存溢出

第一種是目前靜態(tài)內(nèi)部類(lèi)使用比較多的場(chǎng)景,比如JDK集合中的Entry、builder設(shè)計(jì)模式。

HashMap Entry:

解析Java中的static關(guān)鍵字

builder設(shè)計(jì)模式:

public class Person { private String name; private int age; private Person(Builder builder) {this.name = builder.name;this.age = builder.age; } public static class Builder { private String name;private int age; public Builder() {} public Builder name(String name) { this.name = name; return this;}public Builder age(int age) { this.age=age; return this;} public Person build() { return new Person(this);} } public String getName() {return name; } public void setName(String name) {this.name = name; } public int getAge() {return age; } public void setAge(int age) {this.age = age; }} // 在需要?jiǎng)?chuàng)建Person對(duì)象的時(shí)候Person person = new Person.Builder().name('張三').age(17).build();

第二種情況一般出現(xiàn)在多線程場(chǎng)景下,非靜態(tài)內(nèi)部類(lèi)可能會(huì)引發(fā)內(nèi)存溢出的問(wèn)題,比如下面的例子:

public class Task { public void onCreate() {// 匿名內(nèi)部類(lèi), 會(huì)持有Task實(shí)例的引用new Thread() { public void run() {//...耗時(shí)操作 };}.start(); }}

上面這段代碼中的:

new Thread() { public void run() { //...耗時(shí)操作 };}.start();

聲明并創(chuàng)建了一個(gè)匿名內(nèi)部類(lèi)對(duì)象,該對(duì)象持有外部類(lèi)Task實(shí)例的引用,如果在在run方法中做的是耗時(shí)操作,將會(huì)導(dǎo)致外部類(lèi)Task的實(shí)例遲遲不能被回收,如果Task對(duì)象創(chuàng)建過(guò)多,會(huì)引發(fā)內(nèi)存溢出。

優(yōu)化方式:

public class Task { public void onCreate() {SubTask subTask = new SubTask();subTask.start(); } static class SubTask extends Thread {@Overridepublic void run() { //...耗時(shí)操作 } }}1.5、靜態(tài)導(dǎo)入

靜態(tài)導(dǎo)入其實(shí)就是import static,用來(lái)導(dǎo)入某個(gè)類(lèi)或者某個(gè)包中的靜態(tài)方法或者靜態(tài)變量。如下面這段代碼所示:

import static java.lang.Math.PI; public class MathUtils { public static double calCircleArea(double r) {// 可以直接用 Math類(lèi)中的靜態(tài)變量PIreturn PI * r * r; }}

這樣在書(shū)寫(xiě)代碼的時(shí)候確實(shí)能省一點(diǎn)代碼,但是會(huì)影響代碼可讀性,所以一般情況下不建議這么使用。

二.static變量和普通成員變量區(qū)別

static變量和普通成員變量主要有以下4點(diǎn)區(qū)別:

區(qū)別1:所屬不同。static變量屬于類(lèi),不單屬于任何對(duì)象;普通成員變量屬于某個(gè)對(duì)象 區(qū)別2:存儲(chǔ)區(qū)域不同。static變量位于方法區(qū);普通成員變量位于堆區(qū)。 區(qū)別3:生命周期不同。static變量生命周期與類(lèi)的生命周期相同;普通成員變量和其所屬的對(duì)象的生命周期相同。 區(qū)別4:在對(duì)象序列化時(shí)(Serializable),static變量會(huì)被排除在外(因?yàn)閟tatic變量是屬于類(lèi)的,不屬于對(duì)象)三.類(lèi)的構(gòu)造器到底是不是static方法?

關(guān)于類(lèi)的構(gòu)造器是否是static方法有很多爭(zhēng)議,在《java編程思想》一書(shū)中提到“類(lèi)的構(gòu)造器雖然沒(méi)有用static修飾,但是實(shí)際上是static方法”,個(gè)人認(rèn)為這種說(shuō)法有點(diǎn)欠妥,原因如下:

1)在類(lèi)的構(gòu)造器中,實(shí)際上有一個(gè)隱藏的參數(shù)this引用,this是跟對(duì)象綁定的,也就是說(shuō)在調(diào)用構(gòu)造器之前,這個(gè)對(duì)象已經(jīng)創(chuàng)建完畢了才能出現(xiàn)this引用。而構(gòu)造器的作用是干什么的呢?它負(fù)責(zé)在創(chuàng)建一個(gè)實(shí)例對(duì)象的時(shí)候?qū)?shí)例進(jìn)行初始化操作,即jvm在堆上為實(shí)例對(duì)象分配了相應(yīng)的存儲(chǔ)空間后,需要調(diào)用構(gòu)造器對(duì)實(shí)例對(duì)象的成員變量進(jìn)行初始化賦值操作。

2)我們?cè)賮?lái)看static方法,由于static不依賴(lài)于任何對(duì)象就可以進(jìn)行訪問(wèn),也就是說(shuō)和this是沒(méi)有任何關(guān)聯(lián)的。從這一層面去講,類(lèi)的構(gòu)造器不是static方法

3)從JVM指令層面去看,類(lèi)的構(gòu)造器不是static方法,我們先看一下下面這段代碼:

class Person { private String name; public Person(String name) { this.name = name; } public static void create() { }} public class Main { public static void main(String[] args) { Person.create(); Person p = new Person('Jack'); }}

這段代碼反編譯之后的字節(jié)碼如下:

解析Java中的static關(guān)鍵字

從上面可以看出,在調(diào)用static方法是調(diào)用的是invokestatic指令,而在調(diào)用類(lèi)的構(gòu)造器時(shí)實(shí)際上執(zhí)行的是invokespecial指令,而這2個(gè)指令在JVM規(guī)范中的解釋如下:

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokestatic

解析Java中的static關(guān)鍵字

解析Java中的static關(guān)鍵字

可以看出,這2個(gè)指令的用途是完全不同的,invokestatic定義很清楚,就是用來(lái)調(diào)用執(zhí)行static方法,而invokespecial用來(lái)調(diào)用實(shí)例方法,用來(lái)特殊調(diào)用父類(lèi)方法、private方法和類(lèi)的構(gòu)造器。

以上就是解析Java中的static關(guān)鍵字的詳細(xì)內(nèi)容,更多關(guān)于Java static 關(guān)鍵字的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 午夜剧场刺激性爽免费视频 | 欧美日韩中文字幕久久伊人 | 国产精品美女一区二区三区 | 黑人多p| 亚洲国产色婷婷精品综合在线观看 | 任你躁欧美一级在线精品免费 | 一级一片免费视频播放 | 国产成人精品亚洲77美色 | 亚洲视频在线免费观看 | 午夜男人一级毛片免费 | 久久婷婷是五月综合色狠狠 | 350gao免费永久视频 | 在线观看人成网站深夜免费 | 国产精品色哟哟 | 亚洲欧美国产日产综合不卡 | 婷婷综合在线 | 黄色片免费播放 | 91视在线国内在线播放酒店 | 伦伦影院精品一区 | 中文字幕国产欧美 | 欧美一级一片 | 9久热久re爱免费精品视频 | 亚洲呦呦 | 色图在线观看 | 中文一级黄色片 | 青娱乐久草| 日韩免费a级在线观看 | 色婷婷综合和线在线 | 亚洲国产剧情在线精品视 | 欧洲亚洲精品 | 中文字幕久久久久久久系列 | 日韩另类在线 | 黄p片| 人超级碰碰视频在线观看 | 91麻豆国产在线观看 | 国产美女白丝袜精品_a不卡 | 99视频在线观看高清 | 日韩精品久久一区二区三区 | 国产免费播放一区二区 | 麻豆网站入口 | 亚洲天堂一区二区三区四区 |