第07天 Static關鍵字作用及用法

每天學習一個知識點

?作者簡介:大家好,我是Leo,熱愛Java后端開發者,一個想要與大家共同進步的男人😉😉
🍎個人主頁:Leo的博客
💞當前專欄:每天一個知識點
?特色專欄: MySQL學習
🥭本文內容:第07天 Static關鍵字作用及用法
🖥?個人小站 :個人博客,歡迎大家訪問
📚個人知識庫: 知識庫,歡迎大家訪問

1. 概述

Static是靜態修飾符,什么叫靜態修飾符呢?大家都知道,在程序中任何變量或者代碼都是在編譯時由系統自動分配內存來存儲的,而所謂靜態就是指在編譯后所分配的內存會一直存在,直到程序退出內存才會釋放這個空間,也就是只要程序在運行,那么這塊內存就會一直存在。這樣做有什么意義呢?在Java程序里面,所有的東西都是對象,而對象的抽象就是類,對于一個類而言,如果要使用他的成員,那么普通情況下必須先實例化對象后,通過對象的引用才能夠訪問這些成員,但是用static修飾的成員可以通過類名加“.”進行直接訪問。

官方解釋靜態變量Static Variable)在計算機編程領域指在程序執行前系統就為之靜態分配(也即在運行時中不再改變分配情況)存儲空間的一類變量。與之相對應的是在運行時只暫時存在的自動變量(即局部變量)與以動態分配方式獲取存儲空間的一些對象,其中自動變量的存儲空間在調用棧上分配與釋放。(選自維基百科)

如何理解?為什么要這樣做?例子?

  • 解釋:

首先,先了解一下Java的內存分配:

Java 把內存分為棧內存和堆內存,其中棧內存用來存放一些基本類型的變量、數組和對象的引用,堆內存主要存放一些對象。

什么是句柄: 自己理解的話,其實就是類似于對這些靜態的成員進行編號。

那為什么要這樣做呢?

在 JVM 加載一個類的時候,若該類存在 static 修飾的成員變量和成員方法,則會為這些成員變量和成員方法在固定的位置開辟一個固定大小的內存區域,有了這些“固定”的特性,那么 JVM 就可以非常方便地訪問他們。同時如果靜態的成員變量和成員方法不出作用域的話,它們的句柄都會保持不變。同時 static 所蘊含“靜態”的概念表示著它是不可恢復的,即在那個地方,你修改了,他是不會變回原樣的,你清理了,他就不會回來了。

可能這些有些偏于理論,下面我們通過一些代碼示例來進一步了解Static關鍵字

2. 修飾成員屬性

當我們需要在一個類(class)中定義一個屬性為公共的屬性,就好比說我們需要這個屬性是所有類都是共有的,并且這個屬性的值是同一個。

package com.cisyam.testStatic;/*** @author : Leo* @version 1.0* @date 2023/8/18 11:06* @description :*/
class Book{// 設置一個默認的值static String pub = "清華大學出版社";// 用來和 static 作為對比String description = "描述";// Book 類正常的屬性private String title;private double price;// Book 的構造類public Book(String title, double price) {this.title = title;this.price = price;}// 獲取 Book 的信息public void getInfo(){System.out.println("圖書名稱:"+ this.title + ",價格為:"+ this.price + ",出版社為:"+ pub + ",描述 "+ this.description);}
}public class Test {public static void main(String[] args) {// 實例化三個Book類Book book1 = new Book("Android開發實戰", 69.8);Book book2 = new Book("Java EE開發實戰", 49.8);Book book3 = new Book("Java 開發教程", 79.8);// 在沒有設置 pub 屬性的情況下輸出book1.getInfo();book2.getInfo();book3.getInfo();System.out.println("————————————————————無敵分割線————————————————————");// 我們給 book1 設置一個 pub 屬性Book.pub = "中信出版社";book1.description = "這本書很牛逼,看了你就知道";book1.getInfo();book2.getInfo();book3.getInfo();}
}

控制臺輸出

image-20230818111309548

從控制臺輸出的結果,可以看到:

  • 如果給 屬性 賦默認值,在上面的例子中是(description 和 pub),輸出的結果為都是默認的。
  • 當我們修改了類中 static 關鍵字聲明的屬性,那么只要修改了一次,那么其他所有的對象的這個屬性都給修改了。

通過類調用 static 聲明的屬性

但是基于上面的代碼,我們發現如果是其中的一個類對象就改變了所有的對象的屬性,這樣子操作是不是感覺不是特別好?然后在Java中,如果是使用 static 聲明的屬性值,是可以直接通過類調用的。

public class Test {public static void main(String[] args) {// 實例化三個Book類Book book1 = new Book("Android開發實戰", 69.8);Book book2 = new Book("Java EE開發實戰", 49.8);Book book3 = new Book("Java 開發教程", 79.8);// 在沒有設置 pub 屬性的情況下輸出book1.getInfo();book2.getInfo();book3.getInfo();System.out.println("————————————————————無敵分割線————————————————————");// 我們使用 Book 類直接調用pubBook.pub = "中信出版社";book1.description = "這本書很牛逼,看了你就知道";book1.getInfo();book2.getInfo();book3.getInfo();}
}

沒有實例化類時,調用 static 屬性

package com.cisyam.testStatic;/*** @author : Leo* @version 1.0* @date 2023/8/18 11:19* @description :*/
class Book2{// 設置一個默認的值static String pub = "清華大學出版社";// 用來和 static 作為對比String description = "描述";// Book 類正常的屬性private String title;private double price;// Book 的構造類public Book2(String title, double price) {this.title = title;this.price = price;}// 獲取 Book 的信息public void getInfo(){System.out.println("圖書名稱:"+ this.title + ",價格為:"+ this.price + ",出版社為:"+ pub + ",描述 "+ this.description);}
}public class Test3 {public static void main(String[] args) {// 在沒有實例化對象時,就調用System.out.println(Book.pub);// 沒事實例化對象的時候,去給static屬性賦值上默認值Book2.pub = "北京大學出版社";System.out.println(Book.pub);// 新建一個類,輸入 pub 屬性Book2 book = new Book2("Java", 88);book.getInfo();}
}

控制臺輸出

image-20230818112054747

由此,我們看出,在沒有實例化對象的時候,就可以直接通過類去掉用 static屬性,并且還可以修改 static 的屬性。static 屬性聲明雖然是在類的結構中,但是并不受到對象的控制,是獨立存在的。

static 屬性與非 static 屬性的區別

  • static 聲明的屬性和普通屬性(非 static 屬性)最大的區別在于保存的內存區域不同。static 所修飾的在靜態數據區。而不是在堆和棧。

  • static 屬性與非 static 屬性還有一個最大的區別,就是在于所有非 static 屬性必須產生實例化之后才可以訪問,但是static 屬性不受實例化對象的控制。也就是說,在沒有產生實例化對象的情況下,依然可以使用 static 對象。

3. 修飾成員方法

說明

方法本來就是存放在類的定義當中的。static修飾成員方法的作用是可以使用"類名.方法名"的方式操作方法,避免了先要new出對象的繁瑣和資源消耗。

package com.cisyam.testStatic;/*** @author : Leo* @version 1.0* @date 2023/8/18 11:19* @description :*/
class Test2{public static void sayHello(String name) {System.out.println("Hello," + name);}
}public class Demo {public static void main(String[] args) {Test2.sayHello("Leo");}
}

控制臺輸出

image-20230818112801463

4. 修飾代碼塊

說明

**static **{ }就是靜態塊,當類加載器載入類的時候,這一部分代碼被執行,常用于對靜態變量進行初始化工作。當其他代碼用到這個類,類加載器才會將它載入。

代碼只能執行一次,不能再調用。在靜態塊中,可以訪問靜態變量,調用靜態方法。

如果去掉static,{ }中的代碼則會在創建類對象的時候才執行,(相當于把這部分代碼復制到各個構造函數中),這樣可以實現塊中的內容在多個構造函數中的復用。

package com.cisyam.testStatic;/*** @author : Leo* @version 1.0* @date 2023/8/18 11:29* @description :*/
class Test4{static {System.out.println("靜態代碼塊執行");}{System.out.println("普通代碼塊執行");}public Test4(){System.out.println("This is Test()");}public Test4(String string){System.out.println("This is Test(String string)");}
}public class Demo2 {public static void main(String[] args) {System.out.println("------------------------");Test4 test1 = new Test4();System.out.println("------------------------");Test4 test2 = new Test4("Hello");}
}

控制臺輸出

image-20230818113217885

5. 修飾內部類

static 不能修飾普通類,但可以修飾內部類。原因如下:

static 修飾的東西被我們成為類成員,它會隨著類的加載而加載,比如:靜態代碼塊,靜態成員,靜態方法(這里只是加載,并沒有調用)等等。若把一個Class文件中的外部類設為static,那目的何在呢?難道讓這個類隨著應用的啟動而加載嗎?如果我在這次使用過程中根本沒有使用過這個類,那么是不是就會浪費內存。這樣來說設計不合理,總而言之,設計不合理的地方,Java是不會讓它存在的。

為什么內部類可以使用 static 修飾呢,因為內部類算是類的成員了,如果我們沒有使用靜態來修飾,那么我們在創建內部類的時候就需要先有一個外部類的對象,如果我們一直在使用內部類,那么內存中就會一直存在外部類的引用,而我們有時候只需要使用內部類,不需要外部類,那么還是會浪費內存,甚至會造成內存溢出。使用 static修飾內部類之后,內部類在創建對象時就不需要有外部類對象的引用了。

package com.cisyam.testStatic;public class Singleton {private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}private Singleton (){}public static final Singleton getInstance() {return SingletonHolder.INSTANCE;}
}class Demo3 {public static void main(String[] args) {Singleton singleton = Singleton.getInstance();System.out.println(singleton);}}

6. static加載順序

首先思考,下邊程序是否能編譯通過?若可以編譯通過,那么執行結果是什么?

package com.cisyam.testStatic;/*** @author : Leo* @version 1.0* @date 2023/8/18 11:38* @description :*/
public class User {private static String name;public void setName(String name) {this.name = name;}public static String getName() {return User.name;}
}
public class Test6 {public static void main(String[] args) {User user = new User();user.setName("Leo");System.out.println("user = " + User.getName());}
}

控制臺輸出

image-20230818114056989

從上述結果可見,實例對象可以訪問訪問類變量。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/41769.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/41769.shtml
英文地址,請注明出處:http://en.pswp.cn/news/41769.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【前端|Javascript第5篇】全網最詳細的JS的內置對象文章!

前言 在當今數字時代,前端技術正日益成為塑造用戶體驗的關鍵。我們在開發中需要用到很多js的內置對象的一些屬性來幫助我們更快速的進行開發。或許你是剛踏入前端領域的小白,或者是希望深入了解內置對象的開發者,不論你的經驗如何&#xff0c…

使用Dockerfile制作RocketMq的Docker鏡像(任意版本)

使用dockerfile制作任意版本的docker鏡像 1、Dockerfile 創建文件rocketmq #FROM openjdk:8 FROM java8:1.0 #上面的基礎鏡像可以自己 docker pull LABEL "作者"=aaaaaENV ROCKETMQ_VERSION 5.1.3 # ENV LANG en_US.UTF-8ENV ROCKETMQ_HOME="/home/rocketm…

MATLAB中的代數環概念

在 Simulink 模型中,當存在信號環并且信號環中只存在直接饋通模塊時,將出現代數環。直接饋通表示 Simulink 需要模塊輸入信號的值來計算當前時間步的輸出。這種信號循環會在同一時間步中產生模塊輸出和輸入的循環依存關系。這會導致一個需要在每個時間步…

【【verilog典型電路設計之流水線結構】】

verilog典型電路設計之流水線結構 下圖是一個4位的乘法器結構,用verilog HDL 設計一個兩級流水線加法器樹4位乘法器 對于流水線結構 其實需要做的是在每級之間增加一個暫存的數據用來存儲 我們得到的東西 我們一般來說會通過在每一級之間插入D觸發器來保證數據的聯…

Oracle 數據庫備份

1、使用管理員賬號創建對應的directory目錄 登錄數據庫 sqlplus / as sysdba 創建directory create or replace directory dumpdir as F:\container; 2、給用戶賦予使用該目錄的權限 grant read,write on directory dumpdir to Scott; 查看創建的目錄位置 select * fro…

OpenCV-Python中的圖像處理-圖像特征

OpenCV-Python中的圖像處理-圖像特征 圖像特征Harris角點檢測亞像素級精度的角點檢測Shi-Tomasi角點檢測SIFT(Scale-Invariant Feature Transfrom)SURF(Speeded-Up Robust Features)FAST算法BRIEF(Binary Robust Independent Elementary Features)算法ORB (Oriented FAST and R…

JavaScript判空設默認值的幾種寫法

前端面試題庫 (面試必備) 推薦:★★★★★ 地址:前端面試題庫 實踐中需要給某個變量賦值時,若數據來源不可控,通常會給它設置一個默認值(就像空對象模式一樣)。JavaScri…

python編程中有哪些方便的調試方法

大家好,給大家分享一下一個有趣的事情,很多人還不知道這一點。下面詳細解釋一下。現在讓我們來看看! 對于每個程序開發者來說,調試幾乎是必備技能。常用Pycharm編輯器里的方法有Print大法、log大法,但缺少類似Matlab的…

敏感掛載binfmt_misc容器逃逸復現和分析

前言 對于/proc下有很多掛載會導致容器逃逸,其中binfmt_misc就是一種可以利用的逃逸掛載 binfmt_mics 實驗 touch test_fmt_intp echo aaa > test_fmt echo #!/bin/sh > test_fmt_intp echo >> test_fmt_intp chmod x test_fmt_intp echo :test_fmt…

怎么開通Tik Tok海外娛樂公會呢?

TikTok作為全球知名的社交媒體平臺,吸引了數億用戶的關注和參與。許多公司和個人渴望通過開通TikTok直播公會進入這一領域,以展示自己的創造力和吸引更多粉絲。然而,成為TikTok直播公會并非易事,需要滿足一定的門檻和申請找cmxyci…

【日常積累】Linux之init系統學習

init系統簡介: Linux 操作系統的啟動首先從 BIOS 開始,接下來進入 boot loader,由 bootloader 載入內核,進行內核初始化。內核初始化的最后一步就是啟動 pid 為 1 的 init 進程,這個進程是系統的第一個進程,它負責產生…

銀河麒麟服務器v10 sp1 .Net6.0 上傳文件錯誤

上一篇:銀河麒麟服務器v10 sp1 部署.Net6.0 http https_csdn_aspnet的博客-CSDN博客 .NET 6之前,在Linux服務器上安裝 libgdiplus 即可解決,libgdiplus是System.Drawing.Common原生端跨平臺實現的主要提供者,是開源mono項目。地址…

封裝form表單

目錄 1. 源碼 2. 其他頁面引用 ps&#xff1a;請看完看明白再復用 1. 源碼 <template><div style"width: 100%; height: 100%" class"form-condition"><!-- 普通表單 --><el-card shadow"hover" class"cardheigh…

AQS的原理及應用

文章目錄 AQS引言AQS 的原理AQS 應用舉例1:Semaphore舉例2:ReentrantLockAQS 的案例分析問題背景解決方案AQS 引言 在我們的日常生活和工作中,往往需要協調各個線程之間的執行順序和資源使用,而AQS(AbstractQueuedSynchronizer)即為 Java 并發包中提供的一種解決辦法。…

ubuntu 部署 ChatGLM-6B 完整流程 模型量化 Nvidia

ubuntu 部署 ChatGLM-6B 完整流程 模型量化 Nvidia 初環境與設備環境準備克隆模型代碼部署 ChatGLM-6B完整代碼 ChatGLM-6B 是一個開源的、支持中英雙語的對話語言模型&#xff0c;基于 General Language Model (GLM) 架構&#xff0c;具有 62 億參數。結合模型量化技術&#x…

力扣 322. 零錢兌換

題目來源&#xff1a;https://leetcode.cn/problems/coin-change/description/ C題解&#xff08;來源代碼隨想錄&#xff09;&#xff1a;題目中說每種硬幣的數量是無限的&#xff0c;可以看出是典型的完全背包問題。動規五部曲分析如下&#xff1a; 確定dp數組以及下標的含義…

深入理解設計模式-創建型之建造者模式(與工廠區別)

什么是建造者設計模式&#xff1f;和工廠設計模式有什么區別 建造者設計模式&#xff08;Builder Design Pattern&#xff09;和工廠設計模式&#xff08;Factory Design Pattern&#xff09;都是面向對象設計中的創建型模式&#xff0c;但它們解決的問題和應用場景有所不同。…

原碼、反碼、補碼,進制轉換,有符號數和無符號數轉換

計算機底層存儲數據時&#xff0c;存儲的是數據對應的二進制數字。對于整型數據&#xff0c;其二進制表示形式有三種&#xff0c;分別是&#xff1a;原碼、反碼、補碼&#xff0c;而實際存儲的是整型數據的補碼。 原碼、反碼以及補碼都是有符號的&#xff0c;其中最高位存放符…

帶你掌握Stable Diffution商業級玩法

課程介紹 學習地址 《Stable Diffusion商業級玩法》通過詳細講解AI繪畫技巧、實操演示和個性化指導&#xff0c;幫助您從零基礎成為繪畫高手&#xff0c;幫助您有效推廣產品或服務&#xff0c;提升市場份額。教您掌握穩定擴散繪畫技巧&#xff0c;開啟藝術創作新篇章。

Opencv 之ORB特征提取與匹配API簡介及使用例程

Opencv 之ORB特征提取與匹配API簡介及使用例程 ORB因其速度較快常被用于視覺SLAM中的位姿估計、視覺里程、圖像處理中的特征提取與匹配及圖像拼接等領域本文將詳細給出使用例程及實現效果展示 1. API 簡介 創建 static Ptr<ORB> cv::ORB::create (int nfeatures 500…