- 餓漢式
//餓漢式-創建對象實例的時候直接初始化
//空間換時間
//在類進行加載的時候,完成了實例化操作,一直存在於jvm中,需要的時候 直接去jvm拿
//靜態的屬性只會加載一次,第一次實例化的時候分配空間,以後再實例化這個類的時候。不會再分配內存空間
public class SingletonOne {
// 1.創建類中私有構造
private SingletonOne() {
}
// 2.創建該類型的私有靜態實例
private static SingletonOne instance=new SingletonOne();
// 3.創建公有靜態方法返回靜態實例對象
public static SingletonOne getInstance() {
return instance;
}
}
- 懶漢式
//懶漢式-類內實例對象創建時,並不直接初始化,直到第一次調用get方法時,完成第一次初始化操作
//用時間換空間的編碼格式
public class SingletonTwo {
// 創建私有構造方法
private SingletonTwo() {
}
// 創建靜態的該類實例對象
private static SingletonTwo instance=null;
// 3.創建公有靜態方法返回靜態實例對象
public static SingletonTwo getInstance() {
if(instance==null) {
return instance=new SingletonTwo();
}else {
return instance;
}
}
}
public class Tets {
public static void main(String[] args) {
// TODO Auto-generated method stub
// SingletonOne one=SingletonOne.getInstance();
// SingletonOne two=SingletonOne.getInstance();
// System.out.println(one);
// System.out.println(two);
SingletonTwo one1=SingletonTwo.getInstance();
SingletonTwo two1=SingletonTwo.getInstance();
System.out.println(one1);
System.out.println(two1);
}
輸出結果:
com.imooc.singleton.SingletonTwo@7852e922
com.imooc.singleton.SingletonTwo@7852e922
常見問題:
1、public static SingletonOne getInstance() {}
a. 該方法爲什麼用靜態的?爲什麼要用這個類的類型作爲返回值?
b. 只能叫這個名字麼?
a、getInstance()
方法的作用是實現該類對象的返回,因此需要設置該類類型作爲方法返回值;至於static,則是因爲對於單例模式而言,需要在類外能在無需產生對象實例的情況下,完成這個方法的調用,因此該方法需要設置爲static。
b、方法名並不限定,只是一種推薦命名,見名知義。
2、關於對象實例化、對象引用、對象聲明的關係
完整的對象實例化的過程,可以分爲聲明和實例化兩部分,這兩步可以拆分也可以整合。
譬如:
和
結合這段代碼,one表示對象名,也可稱爲對象引用。
3、不是說,單例模式只能有一個對象嗎,爲什麼在測試類裏出現了兩個SingletonOne的對象也不報錯呢?
所謂單例模式只能有一個對象,是指無論應用該類型產生多少對象,都是指向唯一的堆空間,所以測試類中,只是聲明瞭兩個對象的引用指向了同一內存空間,不會報錯。
4、單例模式中的類成員是否需要加final修飾?
從語法層面來說:
餓漢式:加入final修飾對於模式實現本身無影響
懶漢式:加入final修飾產生編譯報錯,提示信息爲:無法對final修飾的成員進行操作。
原因是,final修飾的靜態成員,如果在定義時未進行實例化,則需要在靜態代碼塊中去實現,而不能到類方法中才進行實例化。
從應用層面來說:
如果餓漢式的程序代碼中不僅涉及創建對象及返回的功能,還包括其他的功能,譬如資源回收等,就不能假如final修飾,會影響程序功能實現。
總結:
-
懶漢式中不能加入final。
-
如果在餓漢式代碼中,對類實例只涉及創建和返回方法,可以加入final修飾。