iT邦幫忙

2024 iThome 鐵人賽

DAY 22
0
自我挑戰組

前端工程師的java學習紀錄系列 第 22

Day22-單例模式、初始化區塊

  • 分享至 

  • xImage
  •  

單例模式

當創造一個class 時,不希望他可以有多個實例 ,而是希望整個Java的應用中,只使用同一個class ,這時候可以使用單例模式去定義這個class

最主要分為兩種實例化 的方式

  1. 餓漢式 (Eager Initialization):
public class MyHouse {
	private static MyHouse instance = new MyHouse();
	private static String kitchen = "kitchen";
	private MyHouse(){};
	
	
	public static MyHouse getInstance() {
		return instance;
	}
	
	public static void cook() {
		System.out.println("Use " + kitchen + " to cook");
	}
}

餓漢式會在定義類的時候就將它實例化 ,優點是好寫,且在線程 上是安全的,但是相對來說,它也會造成資源的浪費,會在一開始載入類時就先實例化

  1. 懶漢式 (Lazy Initialization):
public class MyHouse1 {
	private static MyHouse1 instance;
	private static String kitchen = "kitchen";
	private MyHouse1(){};
	
	
	public static MyHouse1 getInstance() {
		if(instance == null) {
			instance = new MyHouse1();
		}
		return instance;
	}
	
	public static void cook() {
		System.out.println("Use " + kitchen + " to cook");
	}
}

懶漢式在定義類的時只會宣告它的變數名 ,當需要使用時才會判斷是否已經實例化 ,優點是不浪費資源,但是在多線程 時上可能會出現問題。

public class MyHouseTest {
	public static void main(String[] args) {
		// 1
		MyHouse house1 = MyHouse.getInstance();
		
		house1.cook(); // Use kitchen to cook
		
		// 2
		MyHouse1 house2 = MyHouse1.getInstance();
		house2.cook(); // Use kitchen to cook
	}
}

MyHouse 在還沒有宣告house1 時(如註解1的位置),MyHouse 其實已經實例化 了,而MyHouse1 則是在宣告了house2 時(如註解2的位置),Java才會先去判斷MyHouse1 是否已經有實例化 ,如果沒有才會去將它實例化

前面提到的多線程 有可能會有問題則是因為,假設今天同時宣告多個MyHouse1.getInstance(); 時,有可能會造成同時認為尚未實例化 MyHouse1 ,進而將它實例化多次。

💡多線程的內容後面會再提


初始化區塊

前面講過一個class 有許多的成員,今天要再來講它的另外一個成員初始化區塊初始化區塊 也只有分成兩種靜態初始化區塊實例初始化區塊

使用的方式:

public class Person {
	String name;
	static country;
	//沒有參數的構造器
	Person(){}
	
	// 實例初始化區塊
	{
		System.out.println("This is Instance Initializer Block");
		name = "Tom";
	}
	
	// 靜態初始化區塊
	static {
		System.out.println("This is Static Initializer Block");
		country = "Taiwan";
	}
}
public class PersonTest {
	public static void main(String[] args) {
		Person person = new Person();
		Person person1 = new Person();
	}
}
This is Static Initializer Block

This is Instance Initializer Block
This is Instance Initializer Block

實例初始化區塊 只需要在class 中使用{} 當中的程式碼就會在實例化 這個class 時執行裡面的程式碼,例如上面出現了兩次This is Instance Initializer Block

靜態初始化區塊靜態屬性靜態方法一樣,它只會在class 載入時執行一次。

實例初始化區塊 :可以使用屬性方法靜態屬性靜態方法

靜態初始化區塊 :可以使用靜態屬性靜態方法

通常使用初始化區塊 可能會是因為,靜態屬性 中,要賦值時可能要先做一些程式碼的操作再進行賦值,這時候可以使用靜態初始化區塊 ;或者是當構造器中有相同的程式碼時,這時候也可以使用實例初始化區塊 將相同的程式碼放到實例初始化區塊 中(也可以直接使用this 的方式去使用其他構造器)。

💡不要在構造器中對靜態屬性進行任何操作


上一篇
Day21-Static
下一篇
Day23-final
系列文
前端工程師的java學習紀錄38
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言