首頁 > 軟體

Java超詳細透徹講解static

2022-05-17 13:00:48

1. 引入

當我們編寫一個類時,其實就是在描述其物件的屬性和行為,而並沒有產生實質上的物件, 只有通過new關鍵字才會產生出物件,這時系統才會分配記憶體空間給物件,其方法才可以供外部呼叫。我們有時候希望無論是否產生了物件或無論產生了多少物件的情況下,某些特定的資料在記憶體空間裡只有一份。

例如所有的中國人都有個國家名稱,每一箇中國人都共用這個國家名稱,不必在每一箇中國人的範例物件中都單獨分配一個用於代表國家名稱的變數。

2. 理解

static:靜態的

3. 使用

3.1 使用範圍

在Java類中,可用static修飾屬性、方法、程式碼塊、內部類

3.2 static修飾屬性

3.2.1 設計思想

類屬性作為該類各個物件之間共用的變數。在設計類時,分析哪些屬性不因物件的不同而改變,將這些屬性設定為類屬性。相應的方法設定為類方法。

3.2.2 分類

屬性,按是否使用static修飾,又分為:

靜態屬性(靜態變數或類變數)vs 非靜態屬性(範例變數)

範例變數:我們建立了類的多個物件,每個物件都獨立的擁有一套類中的非靜態屬性。當修改其中一個物件中的非靜態屬性時,不會導致其他物件中同樣的屬性值的修改。

靜態變數:我們建立了類的多個物件,多個物件共用同一個靜態變數。當通過某一個物件修改靜態變數時,會導致其他物件呼叫此靜態變數時,是修改過了的。

3.2.3 注意

靜態變數隨著類的載入而載入。可以通過"類.靜態變數"的方式進行呼叫。

靜態變數的載入要早於物件的建立。

修飾的成員,被所有物件所共用。

存取許可權允許時,可不建立物件,直接被類呼叫。

由於類只會載入一次,則靜態變數在記憶體中也只會存在一份:存在方法區的靜態域中。

無論建立多少個物件,靜態資料都只佔用一份儲存區域。

static關鍵字不能應用於區域性變數, 因此它只能作用於域。

① 如果一個域是靜態的基本型別域,且也沒有對它進行初始化,那麼它就會獲得基本型別的標準初值。

② 如果它是一個物件參照,那麼它的預設初始化值就是null

靜態變數與範例變數可修飾的範圍區別:

 靜態變數範例變數
yesno
物件yesyes

3.2.4 舉例

靜態屬性舉例: ① System.out;Math.PI;

應用舉例:

應用舉例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);
    } 
}

應用舉例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; // 不用建立物件就可以存取靜態成員
    } 
}

應用舉例3:

public class StaticDemo {
    public static void main(String args[]) {
      Person.total = 100; // 不用建立物件就可以存取靜態成員
      //存取方式:類名.類屬性,類名.類方法
      System.out.println(Person.total);
      Person c = new Person();
      System.out.println(c.total); //101
    }
}

3.2.5 類變數記憶體解析

圖解1:

圖解2:

3.3 static修飾方法

3.3.1 設計思想

如果方法與呼叫者無關,則這樣的方法通常被宣告為類方法,由 於不需要建立物件就可以呼叫類方法,從而簡化了方法的呼叫。

3.3.2 理解

static修飾方法為靜態方法。

3.3.3 使用

沒有物件的範例時,可以用類名.方法名()的形式存取由static修飾的類方法。

靜態方法與非靜態方法可修飾的範圍區別:

 靜態方法非靜態方法
yesno
物件yesyes

3.3.4 注意

因為不需要範例就可以存取static方法,因此static方法內部不能有this。(也不能有super)

static修飾的方法不能被重寫。

靜態方法中,只能呼叫靜態的方法或屬性。

非靜態方法中,既可以呼叫非靜態的方法或屬性,也可以呼叫靜態的方法或屬性。

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("中國人吃中餐");
		//呼叫非靜態結構
		this.info();
		System.out.println("name :" +name);
		//呼叫靜態結構
		walk();
		System.out.println("nation : " + nation);
	}	
	public static void show(){
		System.out.println("我是一箇中國人!");
		//不能呼叫非靜態的結構
//		eat();
//		name = "Tom";
		//可以呼叫靜態的結構
		System.out.println(Chinese.nation);
		walk();
	}	
	public void info(){
		System.out.println("name :" + name +",age : " + age);
	}	
	public static void walk(){		
	}
}

4. 注意

關於靜態屬性和靜態方法的使用,可都從生命週期的角度去理解。

開發中,如何確定一個屬性是否要宣告為static的?

屬性是可以被多個物件所共用的,不會隨著物件的不同而不同的。

類中的常數也常常宣告為static

開發中,如何確定一個方法是否要宣告為static的?

操作靜態屬性的方法,通常設定為static的。

工具類中的方法,習慣上宣告為static的。 比如:MathArraysCollections

5. 單例 (Singleton)設計模式

5.1 概述

設計模式是在大量的實踐中總結和理論化之後優選的程式碼結構、程式設計風格、 以及解決問題的思考方式。設計模免去我們自己再思考和摸索。就像是經典的棋譜,不同的棋局,我們用不同的棋譜。”套路”

所謂類的單例設計模式,就是採取一定的方法保證在整個的軟體系統中,對某個類只能存在一個物件範例,並且該類只提供一個取得其物件範例的方法。 如果我們要讓類在一個虛擬機器器中只能產生一個物件,我們應該怎麼做呢?

① 我們首先必須將類的構造器的存取許可權設定為private

這樣,就不能用new操作符在類的外部產生類的物件了,但在類內部仍可以產生該類的物件。

② 其次,指向類內部產生的該類物件的變數也必須定義成靜態的

因為在類的外部開始還無法得到類的物件,只能呼叫該類的某個靜態方法以返回類內部建立的物件, 靜態方法只能存取類中的靜態成員變數,所以,指向類內部產生的該類物件的變數也必須定義成靜態的。

5.2 優點

由於單例模式只生成一個範例,減少了系統效能開銷,當一個物件的產生需要比較多的資源時,如讀取設定、產生其他依賴物件時,則可以通過在應用啟動時直接產生一個單例物件,然後永久駐留記憶體的方式來解決。

5.3 單例設計模式-餓漢式

class Singleton {
    // 1.私有化構造器
    private Singleton() {
    }
    // 2.內部提供一個當前類的範例
    // 4.此範例也必須靜態化
    private static Singleton single = new Singleton();
    // 3.提供公共的靜態的方法,返回當前類的物件
    public static Singleton getInstance() {
    return single; 
    } 
}

5.4 單例設計模式-懶漢式

(1)單例設計模式-懶漢式(執行緒不安全)

class Singleton {
    // 1.私有化構造器
    private Singleton() {
    }
    // 2.內部提供一個當前類的範例
    // 4.此範例也必須靜態化
    private static Singleton single;
    // 3.提供公共的靜態的方法,返回當前類的物件
    public static Singleton getInstance() {
      if(single == null) {
      single = new Singleton();
      }
     return single; 
     } 
}

(2)單例設計模式-懶漢式(執行緒安全)

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 應用場景

網站的計數器,一般也是單例模式實現,否則難以同步。

應用程式的紀錄檔應用,一般都使用單例模式實現,這一般是由於共用的紀錄檔檔案一直處於開啟狀態,因為只能有一個範例去操作,否則內容不好追加。

資料庫連線池的設計一般也是採用單例模式,因為資料庫連線是一種資料庫資源。

專案中,讀取組態檔的類,一般也只有一個物件。沒有必要每次使用設定 檔案資料,都生成一個物件去讀取。

Application也是單例的典型應用。

WindowsTask Manager (工作管理員)就是很典型的單例模式。

WindowsRecycleBin (回收站)也是典型的單例應用。在整個系統執行過程中,回收站一直維護著僅有的一個範例。

到此這篇關於Java超詳細透徹講解static的文章就介紹到這了,更多相關Java static內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com