Java超詳細(xì)透徹講解static
1. 引入
當(dāng)我們編寫一個類時,其實(shí)就是在描述其對象的屬性和行為,而并沒有產(chǎn)生實(shí)質(zhì)上的對象, 只有通過new關(guān)鍵字才會產(chǎn)生出對象,這時系統(tǒng)才會分配內(nèi)存空間給對象,其方法才可以供外部調(diào)用。我們有時候希望無論是否產(chǎn)生了對象或無論產(chǎn)生了多少對象的情況下,某些特定的數(shù)據(jù)在內(nèi)存空間里只有一份。
例如所有的中國人都有個國家名稱,每一個中國人都共享這個國家名稱,不必在每一個中國人的實(shí)例對象中都單獨(dú)分配一個用于代表國家名稱的變量。

2. 理解
static:靜態(tài)的
3. 使用
3.1 使用范圍
在Java類中,可用static修飾屬性、方法、代碼塊、內(nèi)部類
3.2 static修飾屬性
3.2.1 設(shè)計(jì)思想
類屬性作為該類各個對象之間共享的變量。在設(shè)計(jì)類時,分析哪些屬性不因?qū)ο蟮牟煌淖?,將這些屬性設(shè)置為類屬性。相應(yīng)的方法設(shè)置為類方法。
3.2.2 分類
屬性,按是否使用static修飾,又分為:
靜態(tài)屬性(靜態(tài)變量或類變量)vs 非靜態(tài)屬性(實(shí)例變量)
實(shí)例變量:我們創(chuàng)建了類的多個對象,每個對象都獨(dú)立的擁有一套類中的非靜態(tài)屬性。當(dāng)修改其中一個對象中的非靜態(tài)屬性時,不會導(dǎo)致其他對象中同樣的屬性值的修改。
靜態(tài)變量:我們創(chuàng)建了類的多個對象,多個對象共享同一個靜態(tài)變量。當(dāng)通過某一個對象修改靜態(tài)變量時,會導(dǎo)致其他對象調(diào)用此靜態(tài)變量時,是修改過了的。
3.2.3 注意
靜態(tài)變量隨著類的加載而加載??梢酝ㄟ^"類.靜態(tài)變量"的方式進(jìn)行調(diào)用。
靜態(tài)變量的加載要早于對象的創(chuàng)建。
修飾的成員,被所有對象所共享。
訪問權(quán)限允許時,可不創(chuàng)建對象,直接被類調(diào)用。
由于類只會加載一次,則靜態(tài)變量在內(nèi)存中也只會存在一份:存在方法區(qū)的靜態(tài)域中。
無論創(chuàng)建多少個對象,靜態(tài)數(shù)據(jù)都只占用一份存儲區(qū)域。
static關(guān)鍵字不能應(yīng)用于局部變量, 因此它只能作用于域。
① 如果一個域是靜態(tài)的基本類型域,且也沒有對它進(jìn)行初始化,那么它就會獲得基本類型的標(biāo)準(zhǔn)初值。
② 如果它是一個對象引用,那么它的默認(rèn)初始化值就是null。
靜態(tài)變量與實(shí)例變量可修飾的范圍區(qū)別:
| 靜態(tài)變量 | 實(shí)例變量 | |
|---|---|---|
| 類 | yes | no |
| 對象 | 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:這是一個圓radius:2.0
c2.display();//name:這是一個圓radius:3.0
}
}
class Circle {
private double radius;
public static String name = "這是一個圓";
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)建對象就可以訪問靜態(tài)成員
}
}
應(yīng)用舉例3:
public class StaticDemo {
public static void main(String args[]) {
Person.total = 100; // 不用創(chuàng)建對象就可以訪問靜態(tài)成員
//訪問方式:類名.類屬性,類名.類方法
System.out.println(Person.total);
Person c = new Person();
System.out.println(c.total); //101
}
}
3.2.5 類變量內(nèi)存解析
圖解1:

圖解2:

3.3 static修飾方法
3.3.1 設(shè)計(jì)思想
如果方法與調(diào)用者無關(guān),則這樣的方法通常被聲明為類方法,由 于不需要創(chuàng)建對象就可以調(diào)用類方法,從而簡化了方法的調(diào)用。
3.3.2 理解
static修飾方法為靜態(tài)方法。
3.3.3 使用
沒有對象的實(shí)例時,可以用類名.方法名()的形式訪問由static修飾的類方法。
靜態(tài)方法與非靜態(tài)方法可修飾的范圍區(qū)別:
| 靜態(tài)方法 | 非靜態(tài)方法 | |
|---|---|---|
| 類 | yes | no |
| 對象 | yes | yes |
3.3.4 注意
因?yàn)椴恍枰獙?shí)例就可以訪問static方法,因此static方法內(nèi)部不能有this。(也不能有super)
static修飾的方法不能被重寫。
靜態(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 = "中國";
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
//編譯不通過
// Chinese.name = "張繼科";
c1.eat();
Chinese.show();
//編譯不通過
// Chinese.eat();
// Chinese.info();
}
}
//中國人
class Chinese{
String name;
int age;
static String nation;
public void eat(){
System.out.println("中國人吃中餐");
//調(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("我是一個中國人!");
//不能調(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)方法的使用,可都從生命周期的角度去理解。
開發(fā)中,如何確定一個屬性是否要聲明為static的?
屬性是可以被多個對象所共享的,不會隨著對象的不同而不同的。
類中的常量也常常聲明為static。
開發(fā)中,如何確定一個方法是否要聲明為static的?
操作靜態(tài)屬性的方法,通常設(shè)置為static的。
工具類中的方法,習(xí)慣上聲明為static的。 比如:Math、Arrays、Collections。
5. 單例 (Singleton)設(shè)計(jì)模式
5.1 概述
設(shè)計(jì)模式是在大量的實(shí)踐中總結(jié)和理論化之后優(yōu)選的代碼結(jié)構(gòu)、編程風(fēng)格、 以及解決問題的思考方式。設(shè)計(jì)模免去我們自己再思考和摸索。就像是經(jīng)典的棋譜,不同的棋局,我們用不同的棋譜。”套路”
所謂類的單例設(shè)計(jì)模式,就是采取一定的方法保證在整個的軟件系統(tǒng)中,對某個類只能存在一個對象實(shí)例,并且該類只提供一個取得其對象實(shí)例的方法。 如果我們要讓類在一個虛擬機(jī)中只能產(chǎn)生一個對象,我們應(yīng)該怎么做呢?
① 我們首先必須將類的構(gòu)造器的訪問權(quán)限設(shè)置為private
這樣,就不能用new操作符在類的外部產(chǎn)生類的對象了,但在類內(nèi)部仍可以產(chǎn)生該類的對象。
② 其次,指向類內(nèi)部產(chǎn)生的該類對象的變量也必須定義成靜態(tài)的
因?yàn)樵陬惖耐獠块_始還無法得到類的對象,只能調(diào)用該類的某個靜態(tài)方法以返回類內(nèi)部創(chuàng)建的對象, 靜態(tài)方法只能訪問類中的靜態(tài)成員變量,所以,指向類內(nèi)部產(chǎn)生的該類對象的變量也必須定義成靜態(tài)的。
5.2 優(yōu)點(diǎn)
由于單例模式只生成一個實(shí)例,減少了系統(tǒng)性能開銷,當(dāng)一個對象的產(chǎn)生需要比較多的資源時,如讀取配置、產(chǎn)生其他依賴對象時,則可以通過在應(yīng)用啟動時直接產(chǎn)生一個單例對象,然后永久駐留內(nèi)存的方式來解決。
5.3 單例設(shè)計(jì)模式-餓漢式
class Singleton {
// 1.私有化構(gòu)造器
private Singleton() {
}
// 2.內(nèi)部提供一個當(dāng)前類的實(shí)例
// 4.此實(shí)例也必須靜態(tài)化
private static Singleton single = new Singleton();
// 3.提供公共的靜態(tài)的方法,返回當(dāng)前類的對象
public static Singleton getInstance() {
return single;
}
}
5.4 單例設(shè)計(jì)模式-懶漢式
(1)單例設(shè)計(jì)模式-懶漢式(線程不安全)
class Singleton {
// 1.私有化構(gòu)造器
private Singleton() {
}
// 2.內(nèi)部提供一個當(dāng)前類的實(shí)例
// 4.此實(shí)例也必須靜態(tài)化
private static Singleton single;
// 3.提供公共的靜態(tài)的方法,返回當(dāng)前類的對象
public static Singleton getInstance() {
if(single == null) {
single = new Singleton();
}
return single;
}
}
(2)單例設(shè)計(jì)模式-懶漢式(線程安全)
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)用場景
網(wǎng)站的計(jì)數(shù)器,一般也是單例模式實(shí)現(xiàn),否則難以同步。
應(yīng)用程序的日志應(yīng)用,一般都使用單例模式實(shí)現(xiàn),這一般是由于共享的日志文件一直處于打開狀態(tài),因?yàn)橹荒苡幸粋€實(shí)例去操作,否則內(nèi)容不好追加。
數(shù)據(jù)庫連接池的設(shè)計(jì)一般也是采用單例模式,因?yàn)閿?shù)據(jù)庫連接是一種數(shù)據(jù)庫資源。
項(xiàng)目中,讀取配置文件的類,一般也只有一個對象。沒有必要每次使用配置 文件數(shù)據(jù),都生成一個對象去讀取。
Application也是單例的典型應(yīng)用。
Windows的Task Manager (任務(wù)管理器)就是很典型的單例模式。
Windows的RecycleBin (回收站)也是典型的單例應(yīng)用。在整個系統(tǒng)運(yùn)行過程中,回收站一直維護(hù)著僅有的一個實(shí)例。
到此這篇關(guān)于Java超詳細(xì)透徹講解static的文章就介紹到這了,更多相關(guān)Java static內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java連接Sql數(shù)據(jù)庫經(jīng)常用到的操作
這篇文章主要介紹了Java連接Sql數(shù)據(jù)庫經(jīng)常用到的操作的相關(guān)資料,需要的朋友可以參考下2016-02-02
Mybatis查詢數(shù)據(jù)的項(xiàng)目實(shí)現(xiàn)
MyBatis通過XML配置文件或注解,把Java對象映射到對應(yīng)的數(shù)據(jù)庫表中,實(shí)現(xiàn)對象關(guān)系和數(shù)據(jù)關(guān)系的互相轉(zhuǎn)換,從而使得Java應(yīng)用程序能夠更簡單的操作和讀取數(shù)據(jù)庫,本文就詳細(xì)的介紹一下如何實(shí)現(xiàn),感興趣的可以了解一下2023-09-09
Java發(fā)送https請求并跳過ssl證書驗(yàn)證方法
最近在負(fù)責(zé)一個對接第三方服務(wù)的事情,在對接期間因?yàn)榈谌椒?wù)為https的請求,這篇文章主要給大家介紹了關(guān)于Java發(fā)送https請求并跳過ssl證書驗(yàn)證的相關(guān)資料,需要的朋友可以參考下2023-11-11
Spring根據(jù)URL參數(shù)進(jìn)行路由的方法詳解
這篇文章主要給大家介紹了關(guān)于Spring根據(jù)URL參數(shù)進(jìn)行路由的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起來看看吧。2017-12-12
Scala 操作Redis使用連接池工具類RedisUtil
這篇文章主要介紹了Scala 操作Redis使用連接池工具類RedisUtil,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06

