1. java的enum到底有什麼用
簡單的說,枚舉就像是一個常量的集合,到時候只用其中一個值判斷。
如:enum.winter
if(string.equals(enum.winter)){
System.out.println("winter");
}
else if(string.equals(enum.spring)){
System.out.println("spring");
}
在項目中都是 類似的用途
別的用途也有 不太熟 呵呵
2. java中的枚舉到底有什麼作用
枚舉是一種規范它規范了參數的形式,這樣就可以不用考慮類型的不匹配並且顯式的替代了int型參數可能帶來的模糊概念 枚舉像一個類,又像一個數組。
Enum作為Sun全新引進的一個關鍵字,看起來很象是特殊的class, 它也可以有自己的變數,可以定義自己的方法,可以實現一個或者多個介面。 當我們在聲明一個enum類型時,我們應該注意到enum類型有如下的一些特徵。
1.它不能有public的構造函數,這樣做可以保證客戶代碼沒有辦法新建一個enum的實例。
2.所有枚舉值都是public , static , final的。注意這一點只是針對於枚舉值,我們可以和在普通類裡面定義 變數一樣定義其它任何類型的非枚舉變數,這些變數可以用任何你想用的修飾符。
3.Enum默認實現了java.lang.Comparable介面。
4.Enum覆載了了toString方法,因此我們如果調用Color.Blue.toString()默認返回字元串」Blue」.
5.Enum提供了一個valueOf方法,這個方法和toString方法是相對應的。調用valueOf(「Blue」)將返回Color.Blue.因此我們在自己重寫toString方法的時候就要注意到這一點,一把來說應該相對應地重寫valueOf方法。
6.Enum還提供了values方法,這個方法使你能夠方便的遍歷所有的枚舉值。
7.Enum還有一個oridinal的方法,這個方法返回枚舉值在枚舉類種的順序,這個順序根據枚舉值聲明的順序而定,這里Color.Red.ordinal()返回0。
了解了這些基本特性,我們來看看如何使用它們。
1.遍歷所有有枚舉值. 知道了有values方法,我們可以輕車熟路地用ForEach循環來遍歷了枚舉值了。
for (Color c: Color.values())
System.out.println(「find value:」 + c);
2.在enum中定義方法和變數,比如我們可以為Color增加一個方法隨機返回一個顏色。
public enum Color {
Red,
Green,
Blue;
private static int number = Color.values().length ;
public static Color getRandomColor(){
long random = System.currentTimeMillis() % number;
switch ((int) random){
case 0:
return Color.Red;
case 1:
return Color.Green;
case 2:
return Color.Blue;
default : return Color.Red;
}
}
}
可以看出這在枚舉類型里定義變數和方法和在普通類裡面定義方法和變數沒有什麼區別。唯一要注意的只是變數和方法定義必須放在所有枚舉值定義的後面,否則編譯器會給出一個錯誤。
3.覆載(Override)toString, valueOf方法
前面我們已經知道enum提供了toString,valueOf等方法,很多時候我們都需要覆載默認的toString方法,那麼對於enum我們怎麼做呢。其實這和覆載一個普通class的toString方法沒有什麼區別。
….
public String toString(){
switch (this){
case Red:
return "Color.Red";
case Green:
return "Color.Green";
case Blue:
return "Color.Blue";
default:
return "Unknow Color";
}
}
….
這時我們可以看到,此時再用前面的遍歷代碼列印出來的是
Color.Red
Color.Green
Color.Blue
而不是
Red
Green
Blue.
可以看到toString確實是被覆載了。一般來說在覆載toString的時候我們同時也應該覆載valueOf方法,以保持它們相互的一致性。
4.使用構造函數
雖然enum不可以有public的構造函數,但是我們還是可以定義private的構造函數,在enum內部使用。還是用Color這個例子。
public enum Color {
Red("This is Red"),
Green("This is Green"),
Blue("This is Blue");
private String desc;
Color(String desc){
this.desc = desc;
}
public String getDesc(){
return this.desc;
}
}
這里我們為每一個顏色提供了一個說明信息, 然後定義了一個構造函數接受這個說明信息。
要注意這里構造函數不能為public或者protected, 從而保證構造函數只能在內部使用,客戶代碼不能new一個枚舉值的實例出來。這也是完全符合情理的,因為我們知道枚舉值是public static final的常量而已。
5.實現特定的介面
我們已經知道enum可以定義變數和方法,它要實現一個介面也和普通class實現一個介面一樣,這里就不作示例了。
6.定義枚舉值自己的方法。
前面我們看到可以為enum定義一些方法,其實我們甚至可以為每一個枚舉值定義方法。這樣,我們前面覆載 toString的例子可以被改寫成這樣。
public enum Color {
Red {
public String toString(){
return "Color.Red";
}
},
Green {
public String toString(){
return "Color.Green";
}
},
Blue{
public String toString(){
return "Color.Blue";
}
};
}
從邏輯上來說這樣比原先提供一個「全局「的toString方法要清晰一些。
總的來說,enum作為一個全新定義的類型,是希望能夠幫助程序員寫出的代碼更加簡單易懂,個
人覺得一般也不需要過多的使用enum的一些高級特性,否則就和簡單易懂的初衷想違背了。
3. Java涓23縐嶈捐℃ā寮忊斺斿崟渚嬫ā寮
Java涓栫晫涓鐨勫崟渚嬪湥孌匡細23縐嶈捐℃ā寮忔帰緔
鍦↗ava緙栫▼涓錛屽崟渚嬫ā寮忓傚悓涓搴фˉ姊侊紝榪炴帴鐫瀵硅薄鐨勭敓鍛藉懆鏈熺$悊鍜屽叏灞璁塊棶鐨勭簿濡欏鉤琛°傝╂垜浠涓璧鋒繁鍏ユ帰璁ㄥ叚縐嶅父瑙佷笖鍚勬湁鐗硅壊鐨勫疄鐜版柟寮忥紝瀹冧滑鍒嗗埆鏄錛氭噿奼夊紡銆侀タ奼夊紡銆佸弻閲嶆鏌ラ攣瀹氥侀潤鎬佸唴閮ㄧ被銆佹灇涓炬硶涓嶵hreadLocal錛屼互鍙婁竴縐嶅壋鏂扮殑娉ㄥ唽寮忓崟渚嬫ā寮忋
娉ㄥ唽寮忓崟渚嬬殑闈╂柊錛氶噰鐢ㄩ潤鎬丮ap綆$悊鍗曚緥瀵硅薄錛屽綋闇瑕佹椂錛屽疄渚嬪寲騫惰繑鍥炪傚湪璇稿傜嚎紼嬫睜銆佹暟鎹搴撹繛鎺ユ睜銆佹棩蹇楀硅薄鍜岄厤緗鏂囦歡絳夊満鏅涓錛屽畠鑳戒繚璇侀珮鏁堜笖綰跨▼瀹夊叏鐨勮塊棶銆
鐒惰岋紝鍗曚緥妯″紡騫墮潪涓甯嗛庨『錛屽畠涔熼潰涓存寫鎴橈細綰跨▼瀹夊叏闂棰橀渶瑕佸閥濡欏湴浣跨敤閿佹満鍒訛紝搴忓垪鍖栨椂鍙鑳戒駭鐢熷氫釜瀹炰緥錛岃繖鏃秗eadResolve()鏂規硶灝辨淳涓婄敤鍦轟簡錛涘弽灝勫彲鑳藉艱嚧縐佹湁鏋勯犲嚱鏁拌緇曡繃錛岃繖鏃舵垜浠闇鎶涘嚭寮傚父浠ョず璀﹀憡銆
緇撹錛氬崟渚嬫ā寮忔槸鎺у埗瀵硅薄鐢熷懡鍛ㄦ湡鍜屽疄鐜板叡浜璧勬簮鐨勫叧閿銆傚湪閫夋嫨鍝縐嶅疄鐜版柟寮忔椂錛屽姟蹇呮潈琛$嚎紼嬪畨鍏ㄣ佸簭鍒楀寲鍜屽弽灝勭殑鑰冮噺錛屼互閬垮厤浠g爜澶嶆潅鎬у崌綰у拰鎬ц兘鐨勯殣鎬ф崯鑰椼傚彧鏈夊湪鎮板綋鐨勬椂鏈猴紝瀹冩墠鑳芥垚涓轟唬鐮佽捐′腑鐨勫緱鍔涘姪鎵嬨
4. 如何寫一個簡單的單例模式
一、基本的實現思路:
單例的實現主要是通過以下兩個步驟:
1、將該類的構造方法定義為私有方法,這樣其他處的代碼就無法通過調用該類的構造方法來實例化該類的對象,只有通過該類提供的靜態方法來得到該類的唯一實例;
2、在該類內提供一個靜態方法,當我們調用這個方法時,如果類持有的引用不為空就返回這個引用,如果類保持的引用為空就創建該類的實例並將實例的引用賦予該類保持的引用。
二、示範如下:
1、枚舉實現單例:
(4)java單例模式枚舉擴展閱讀:
一、單列模式簡介:
單例模式是設計模式中最簡單的形式之一。這一模式的目的是使得類的一個對象成為系統中的唯一實例。要實現這一點,可以從客戶端對其進行實例化開始。因此需要用一種只允許生成對象類的唯一實例的機制,「阻止」所有想要生成對象的訪問。使用工廠方法來限制實例化過程。這個方法應該是靜態方法(類方法),因為讓類的實例去生成另一個唯一實例毫無意義。
二、懶漢與餓漢:
1、懶漢方式:指全局的單例實例在第一次被使用時構建。
2、餓漢方式:指全局的單例實例在類裝載時構建。
三、單例模式的三要點:
1、某個類只能有一個實例。
2、它必須自行創建這個實例。
3、它必須自行向整個系統提供這個實例。
四、優缺點:
1、優點:
①實例控制:單例模式會阻止其他對象實例化其自己的單例對象的副本,從而確保所有對象都訪問唯一實例。
②靈活性:因為類控制了實例化過程,所以類可以靈活更改實例化過程。
2、缺點:
①開銷:雖然數量很少,但如果每次對象請求引用時都要檢查是否存在類的實例,將仍然需要一些開銷。可以通過使用靜態初始化解決此問題。
②可能的開發混淆:使用單例對象(尤其在類庫中定義的對象)時,開發人員必須記住自己不能使用new關鍵字實例化對象。因為可能無法訪問庫源代碼,因此應用程序開發人員可能會意外發現自己無法直接實例化此類。
③對象生存期:不能解決刪除單個對象的問題。在提供內存管理的語言中(例如基於.NET Framework的語言),只有單例類能夠導致實例被取消分配,因為它包含對該實例的私有引用。在某些語言中(如 C++),其他類可以刪除對象實例,但這樣會導致單例類中出現懸浮引用。
5. 設計模式之單例模式
本文開始整個設計模式的系列學習,希望通過不斷的學習,可以對設計模式有整體的掌握,並在項目中根據實際的情況加以利用。
單例模式是指一個類僅允許創建其自身的一個實例,並提供對該實例的訪問許可權。它包含靜態變數,可以容納其自身的唯一和私有實例。它被應用於這種場景——用戶希望類的實例被約束為一個對象。在需要單個對象來協調整個系統時,它會很有幫助。
1、單例類只能有一個實例
2、單例類必須自己創建自己的唯一實例
3、單例類必須給其他所有對象提供這一實例
1.盡量使用懶載入
2.雙重檢索實現線程安全
3.構造方法為private
4.定義靜態的Singleton instance對象和getInstance()方法
單例模式至少有六種寫法。
作為一種重要的設計模式,單例模式的好處有:
1、控制資源的使用,通過線程同步來控制資源的並發訪問
2、控制實例的產生,以達到節約資源的目的
3、控制數據的共享,在不建立直接關聯的條件下,讓多個不相關的進程或線程之間實現通信
Singleton通過將構造方法限定為private避免了類在外部被實例化,在同一個虛擬機范圍內,Singleton的唯一實例只能通過getInstance()方法訪問。但其實通過Java反射機制是能夠實例化構造方法為private的類的,那基本上會使所有的Java單例實現失效。
雖然也是只有一個線程能夠執行,假如線程B先執行,線程B獲得鎖,線程B執行完之後,線程 A獲得鎖,但是此時沒有檢查singleton是否為空就直接執行了,所以還會出現兩個singleton實例的情況。
既然懶漢式是非線程安全的,那就要改進它。最直接的想法是,給getInstance方法加鎖不就好了,但是我們不需要給方法全部加鎖啊,只需要給方法的一部分加鎖就好了。基於這個考慮,引入了雙檢鎖(Double Check Lock,簡稱DCL)的寫法:
使用volatile 的原因:
對於JVM而言,它執行的是一個個Java指令。在Java指令中創建對象和賦值操作是分開進行的,也就是說instance = new Singleton();語句是分兩步執行的。但是JVM並不保證這兩個操作的先後順序,也就是說有可能JVM會為新的Singleton實例分配空間, 然後直接賦值給instance成員,然後再去初始化這個Singleton實例。這樣就使出錯成為了可能,我們仍然以A、B兩個線程為例:
載入一個類時,其內部類不會同時被載入。一個類被載入,當且僅當其某個靜態成員(靜態域、構造器、靜態方法等)被調用時發生。
枚舉類實現單例模式是 effective java 作者極力推薦的單例實現模式,因為枚舉類型是線程安全的,並且只會裝載一次,設計者充分的利用了枚舉的這個特性來實現單例模式,枚舉的寫法非常簡單,而且枚舉類型是所用單例實現中唯一一種不會被破壞的單例實現模式。因為枚舉類沒有構造方法,可以防止反序列化操作。
1、除枚舉方式外, 其他方法都會通過反射的方式破壞單例,反射是通過調用構造方法生成新的對象,所以如果我們想要阻止單例破壞,可以在構造方法中進行判斷,若已有實例, 則阻止生成新的實例,解決辦法如下:
2、如果單例類實現了序列化介面Serializable, 就可以通過反序列化破壞單例,所以我們可以不實現序列化介面,如果非得實現序列化介面,可以重寫反序列化方法readResolve(), 反序列化時直接返回相關單例對象。
Runtime是一個典型的例子,看下JDK API對於這個類的解釋"每個Java應用程序都有一個Runtime類實例,使應用程序能夠與其運行的環境相連接,可以通過getRuntime方法獲取當前運行時。應用程序不能創建自己的Runtime類實例。",這段話,有兩點很重要:
1、每個應用程序都有一個Runtime類實例
2、應用程序不能創建自己的Runtime類實例
只有一個、不能自己創建,是不是典型的單例模式?看一下,Runtime類的寫法:
為了節約系統資源,有時需要確保系統中某個類只有唯一一個實例,當這個唯一實例創建成功之後,我們無法再創建一個同類型的其他對象,所有的操作都只能基於這個唯一實例。為了確保對象的唯一性,我們可以通過單例模式來實現。
單例模式應用的場景一般發現在以下條件下:
(1)資源共享的情況下,避免由於資源操作時導致的性能或損耗等。如上述中的日誌文件,應用配置。
(2)控制資源的情況下,方便資源之間的互相通信。如線程池等。
關於單例模式的漫畫分析: https://mp.weixin.qq.com/s/f-sJIZHr7JUa31gKTllSFQ
單例模式的優缺點、注意事項、使用場景
6. 如何在Java中實現單例模式
單例模式大致有五種寫法,分別為懶漢,惡漢,靜態內部類,枚舉和雙重校驗鎖。
1、懶漢寫法,常用寫法
classLazySingleton{
;
privateLazySingleton(){
}
(){
if(singleton==null){
singleton=newLazySingleton();
}
returnsingleton;
}
}
2、惡漢寫法,缺點是沒有達到lazy loading的效果
classHungrySingleton{
=newHungrySingleton();
privateHungrySingleton(){}
(){
returnsingleton;
}
}
3、靜態內部類,優點:載入時不會初始化靜態變數INSTANCE,因為沒有主動使用,達到Lazy loading
classInternalSingleton{
{
=newInternalSingleton();
}
privateInternalSingleton(){}
(){
returnSingletonHolder.INSTANCE;
}
}
4、枚舉,優點:不僅能避免多線程同步問題,而且還能防止反序列化重新創建新的對象
enumEnumSingleton{
INSTANCE;
publicvoiddoSomeThing(){
}
}
5、雙重校驗鎖,在當前的內存模型中無效
classLockSingleton{
;
privateLockSingleton(){}
//詳見:http://www.ibm.com/developerworks/cn/java/j-dcl.html
(){
if(singleton==null){
synchronized(LockSingleton.class){
if(singleton==null){
singleton=newLockSingleton();
}
}
}
returnsingleton;
}
}
參考自:http://www.oschina.net/code/snippet_107039_6062
7. 設計模式之單例模式
單例設計模式理解起來非常簡單。一個類只允許創建一個對象(或者實例),那這個類就是一個單例類,這種設計模式就叫單例模式。
下面的示例中如果每個類都創建一個 Logger 實例,就可能造成日誌內容被覆蓋的情況。
如果有些數據在系統中只應保存一份,那就比較適合設計為單例類。比如悄伍,配置信息類,全局 ID 生成器等。
要實現一個單例,我們要考慮以下幾點:
懶漢式相對於餓漢式的優勢是 「支持延遲載入」 。但缺點也很明顯,因為使用了 synchronized 關鍵字導致這個方法的 「並發度很低」 。如果這個單例類偶爾會被用到,那這種實現方式還可以接受。但是,如果頻繁地用到,就會導致性能瓶頸,這種實現方式就不可取了。
這是一種既支持延遲載入、又支持高並發的單例實現方式。
在 java1.5 以下 instance = new Singleton(); 有指令重排問題,需要給 instance 成員變數加上 volatile 關鍵字,java1.5 之後不會再這個問題。
這種方式利用了 Java 的靜態內渣知部類,有點類似餓漢式,但又能做到了延遲載入。
當外部類 Singleton 被載入的時候,並不會創建 SingletonHolder 實例對象。只有當調用 getInstance() 方法時,SingletonHolder 才會被載入,這個時候才會創建 instance。insance 的唯一性、創建過程的線程安全性,都由 JVM 來保證。所以,這種實現方法既保證了線程安全,又能做到延遲載入。
這是一種最簡單的實現方式,基於枚舉類型的單例實現。這種實現方式是通過 Java 枚舉類型本身的特性,保證了實例創建的線程安全性和實例的唯一性。
上面的單例類對象是進程唯一的,一個進程只能有一個單例對象。那如何實現一個線程唯一的單例呢?
假設 IdGenerator 是一個線程唯一的單例類。在線程 A 內,我們可以創建一啟梁或個單例對象 a。因為線程內唯一,在線程 A 內就不能再創建新的 IdGenerator 對象了,而線程間可以不唯一,所以,在另外一個線程 B 內,我們還可以重新創建一個新的單例對象 b。
我們通過一個 ConcurrentHashMap 來存儲對象,其中 key 是線程 ID,value 是對象。這樣我們就可以做到,不同的線程對應不同的對象,同一個線程只能對應一個對象。實際上,Java 語言本身提供了 ThreadLocal 工具類,可以更加輕松地實現線程唯一單例。