詳解Java設(shè)計(jì)模式之單例模式
1、單例模式介紹
單例模式(Singleton),保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn)。
通常我們可以讓一個(gè)全局變量使得一個(gè)對(duì)象被訪問(wèn),但它不能防止你 實(shí)例化多個(gè)對(duì)象。一個(gè)最好的辦法就是,讓類自身負(fù)責(zé)保存它的唯一實(shí)例。 這個(gè)類可以保證沒(méi)有其他實(shí)例可以被創(chuàng)建,并且它可以提供一個(gè)訪問(wèn)該實(shí)例 的方法。
1.1 單例模式結(jié)構(gòu)圖
Singleton類,定義一個(gè)GetInstance操作,允許客戶訪問(wèn)它的唯一實(shí)例。GetInstance是一個(gè)靜態(tài)方法,主要負(fù)責(zé)創(chuàng)建自己的唯一實(shí)例。
/** * @author Shier * CreateTime 2023/5/14 9:23 * 單例模式 */ public class Singleton { private static Singleton singleton; /** * 無(wú)參構(gòu)造 防止外部代碼利用new來(lái)實(shí)例化的可能 */ private Singleton() { } /** * 只能通過(guò)此途徑獲取Singleton實(shí)例 * @return */ public static Singleton getInstance() { // 為空,則創(chuàng)建實(shí)例 if (singleton == null) { singleton = new Singleton(); } // 不為空,則已創(chuàng)建,直接返回實(shí)例 return singleton; } }
客戶端:
/** * @author Shier * CreateTime 2023/5/14 9:27 */ public class SingletonClient { public static void main(String[] args) { Singleton instance1 = Singleton.getInstance(); Singleton instance2 = Singleton.getInstance(); if (instance1 == instance2) { System.out.println("兩個(gè)是同一個(gè)實(shí)例對(duì)象"); } } }
最終得到的:“兩個(gè)是同一個(gè)實(shí)例對(duì)象”,因此單例模式保證了可以被唯一實(shí)例化。當(dāng)然單例模式不止這些好處。下面再來(lái)細(xì)說(shuō)
2、具體例子說(shuō)明
假設(shè)我們有一個(gè)流水號(hào)生成器,用于在系統(tǒng)中生成唯一的流水號(hào)。這個(gè)流水號(hào)生成器需要保證在整個(gè)系統(tǒng)中只有一個(gè)實(shí)例存在,以確保生成的流水號(hào)是唯一的。也就是類似于我們?cè)谕饷娉燥堻c(diǎn)菜呀什么的,買單后,商家會(huì)給你一個(gè)單號(hào),到你了,就讓你去拿屬于你的飯菜。
2.1 不使用單例模式
首先,我們創(chuàng)建一個(gè)名為SerialNumberGenerator
的類,用于生成流水號(hào):
/** * @author Shier * CreateTime 2023/5/14 9:30 * 流水號(hào)例子 */ public class SerialNumberGenerator { private int serialNumber; /** * 外界可以實(shí)例化SerialNumberGenerator */ public SerialNumberGenerator() { serialNumber = 0; } public int generateSerialNumber() { serialNumber++; return serialNumber; } }
現(xiàn)在,我們可以在不同的地方創(chuàng)建多個(gè)SerialNumberGenerator
的實(shí)例并嘗試生成流水號(hào):
/** * @author Shier * CreateTime 2023/5/14 9:31 * 客戶端 */ public class Main { public static void main(String[] args) { SerialNumberGenerator generator1 = new SerialNumberGenerator(); int serialNumber1 = generator1.generateSerialNumber(); System.out.println("流水號(hào)1: " + serialNumber1); SerialNumberGenerator generator2 = new SerialNumberGenerator(); int serialNumber2 = generator2.generateSerialNumber(); System.out.println("流水號(hào)2: " + serialNumber2); } }
結(jié)果:
流水號(hào)1: 1
流水號(hào)2: 1
不使用單例模式存在的問(wèn)題:
- 生成重復(fù)流水號(hào):由于我們可以在不同的地方創(chuàng)建多個(gè)
SerialNumberGenerator
實(shí)例,每個(gè)實(shí)例都會(huì)有自己的serialNumber
變量。這可能導(dǎo)致在不同的實(shí)例中生成相同的流水號(hào),從而產(chǎn)生重復(fù)的流水號(hào)。 - 沒(méi)有共享狀態(tài):每個(gè)
SerialNumberGenerator
實(shí)例都會(huì)維護(hù)自己的serialNumber
變量,這導(dǎo)致每個(gè)實(shí)例生成的流水號(hào)不會(huì)互相影響。這意味著如果我們想要全局唯一的流水號(hào),就需要在各個(gè)地方共享同一個(gè)SerialNumberGenerator
實(shí)例,而不是創(chuàng)建多個(gè)實(shí)例。 - 難以管理和控制:在多個(gè)地方分別創(chuàng)建和管理
SerialNumberGenerator
實(shí)例會(huì)增加代碼的復(fù)雜性。我們需要確保在需要流水號(hào)的每個(gè)地方都使用同一個(gè)實(shí)例,否則會(huì)出現(xiàn)上述問(wèn)題。這增加了代碼維護(hù)的難度,并且容易在系統(tǒng)的不同部分中出現(xiàn)錯(cuò)誤使用的情況。 - 重復(fù)的流水號(hào):如果多個(gè)地方都可以創(chuàng)建流水號(hào)生成器的實(shí)例,那么每個(gè)實(shí)例都有可能生成相同的流水號(hào),導(dǎo)致重復(fù)的流水號(hào)出現(xiàn)。
- 資源浪費(fèi):如果每個(gè)部分都創(chuàng)建自己的流水號(hào)生成器實(shí)例,那么會(huì)造成資源的浪費(fèi),例如每個(gè)實(shí)例都需要獨(dú)立維護(hù)和生成流水號(hào)的狀態(tài)。
- 一致性問(wèn)題:如果多個(gè)流水號(hào)生成器實(shí)例同時(shí)生成流水號(hào),可能會(huì)導(dǎo)致不同實(shí)例生成的流水號(hào)在順序上出現(xiàn)混亂。
2.2 使用單例模式
使用單例模式的實(shí)現(xiàn)方式有多種,這里我將使用線程安全的懶漢式單例模式,具體實(shí)現(xiàn)如下:
懶漢式單例模式下面再介紹
/** * @author Shier */ public class SerialNumberGenerator1 { private static volatile SerialNumberGenerator instance; private int serialNumber; /** * 防止直接實(shí)例化SerialNumberGenerator1 */ private SerialNumberGenerator1() { serialNumber = 0; } /** * 獲取SerialNumberGenerator1的唯一方式 * @return */ public static SerialNumberGenerator getInstance() { if (instance == null) { synchronized (SerialNumberGenerator.class) { if (instance == null) { instance = new SerialNumberGenerator(); } } } return instance; } /** * 生成的流水號(hào) * @return */ public int generateSerialNumber() { synchronized (SerialNumberGenerator.class) { serialNumber++; return serialNumber; } } }
在這個(gè)實(shí)現(xiàn)中,我們使用了一個(gè)靜態(tài)變量instance
來(lái)保存SerialNumberGenerator
的唯一實(shí)例。getInstance()
方法返回這個(gè)實(shí)例,如果它不存在,則會(huì)創(chuàng)建一個(gè)新的實(shí)例。generateSerialNumber()
方法負(fù)責(zé)生成流水號(hào),使用synchronized
關(guān)鍵字來(lái)確保線程安全。
現(xiàn)在,我們可以在不同的地方調(diào)用SerialNumberGenerator.getInstance().generateSerialNumber()
來(lái)生成流水號(hào),并確保它們是唯一的:
/** * @author Shier */ public class Main1 { public static void main(String[] args) { int serialNumber1 = SerialNumberGenerator1.getInstance().generateSerialNumber(); System.out.println("流水號(hào) 1: " + serialNumber1); int serialNumber2 = SerialNumberGenerator1.getInstance().generateSerialNumber(); System.out.println("流水號(hào) 2: " + serialNumber2); } }
通過(guò)使用單例模式,我們解決了不使用單例模式存在的問(wèn)題:
- 確保唯一性:
SerialNumberGenerator
的唯一實(shí)例可以在系統(tǒng)中被多次調(diào)用,但它們都會(huì)引用同一個(gè)實(shí)例,因此可以保證生成的流水號(hào)是唯一的。 - 共享狀態(tài):通過(guò)使用單例模式,所有生成的流水號(hào)共享同一個(gè)
serialNumber
變量,從而避免了重復(fù)生成流水號(hào)的問(wèn)題。 - 管理和控制:由于只有一個(gè)
SerialNumberGenerator
實(shí)例存在于系統(tǒng)中,因此我們不必在各個(gè)地方管理和控制實(shí)例的創(chuàng)建和使用,這降低了代碼復(fù)雜性并減少了出錯(cuò)的可能性。
使用單例模式來(lái)實(shí)現(xiàn)流水號(hào)生成器類,可以確保生成的流水號(hào)是唯一的,避免資源浪費(fèi),并保證生成的流水號(hào)順序一致。所有部分都可以通過(guò)訪問(wèn)流水號(hào)生成器的全局訪問(wèn)點(diǎn)來(lái)獲取唯一的流水號(hào),從而簡(jiǎn)化了流水號(hào)的生成和管理。
3、單例模式實(shí)現(xiàn)方式
在上面例子當(dāng)中使用到了懶漢式單例模式,下面我們?cè)賮?lái)看看單例模式的實(shí)現(xiàn)方式:
單例模式的實(shí)現(xiàn)方式有多種,以下是幾種常見的實(shí)現(xiàn)方式:
- 懶漢式(Lazy Initialization):在首次使用時(shí)創(chuàng)建實(shí)例。懶漢式單例模式可以延遲實(shí)例化,避免不必要的資源消耗。但需要考慮線程安全性,可以通過(guò)加鎖或使用雙重檢查鎖定等方式來(lái)確保線程安全。
- 餓漢式(Eager Initialization):在類加載時(shí)即創(chuàng)建實(shí)例。餓漢式單例模式在類加載時(shí)就創(chuàng)建實(shí)例,因此不存在線程安全問(wèn)題。但可能會(huì)提前創(chuàng)建實(shí)例,造成資源浪費(fèi)。
- 靜態(tài)內(nèi)部類(Static Inner Class):利用類的靜態(tài)內(nèi)部類來(lái)實(shí)現(xiàn)單例模式。這種方式可以實(shí)現(xiàn)延遲加載和線程安全,且對(duì)外部類的加載不產(chǎn)生影響。
- 枚舉(Enum):利用枚舉類型實(shí)現(xiàn)單例模式。枚舉類型的實(shí)例是線程安全的,并且保證只有一個(gè)實(shí)例存在。
- 雙重檢查鎖定(Double-Checked Locking):結(jié)合懶漢式和加鎖機(jī)制,通過(guò)雙重檢查來(lái)實(shí)現(xiàn)延遲加載和線程安全。
- 容器(Container):使用容器來(lái)存儲(chǔ)實(shí)例,每次獲取實(shí)例時(shí)先從容器中查找,如果不存在則創(chuàng)建并添加到容器中。這種方式適用于需要管理多個(gè)單例對(duì)象的情況。
以上是常見的幾種單例模式的實(shí)現(xiàn)方式。每種實(shí)現(xiàn)方式都有其適用的場(chǎng)景和特點(diǎn),選擇哪種方式取決于具體的需求和設(shè)計(jì)考慮。同時(shí),需要注意線程安全性和性能等因素,確保實(shí)現(xiàn)的單例模式符合要求。
下面再說(shuō)說(shuō)最常用的懶漢式和餓漢式單例模式實(shí)現(xiàn)
3.1 懶漢式單例模式
在第一次使用時(shí)才創(chuàng)建實(shí)例,稱為懶漢式。實(shí)現(xiàn)方式是在類內(nèi)部定義一個(gè)私有的靜態(tài)變量作為實(shí)例,然后提供一個(gè)公有的靜態(tài)方法來(lái)獲取該實(shí)例。在方法內(nèi)部判斷實(shí)例是否已經(jīng)存在,如果存在則直接返回,如果不存在則創(chuàng)建一個(gè)新的實(shí)例并返回。(我就是很懶,你不用我,我就不管你,當(dāng)你用我的時(shí)候才回去給你提供需要的東西)
public class Singleton { private static Singleton instance; // 私有構(gòu)造函數(shù) private Singleton() {} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
在懶漢式單例模式中,我們將單例對(duì)象的實(shí)例化放在靜態(tài)方法
getInstance()
中。當(dāng)首次調(diào)用getInstance()
時(shí),會(huì)檢查實(shí)例是否已經(jīng)存在。如果實(shí)例為null,表示還未創(chuàng)建,則進(jìn)行實(shí)例化。這種方式實(shí)現(xiàn)了延遲加載,只有在需要使用單例對(duì)象時(shí)才會(huì)創(chuàng)建它。
需要注意的是,在多線程環(huán)境下,懶漢式單例模式需要考慮線程安全性。上述代碼的實(shí)現(xiàn)并未考慮線程安全,可能會(huì)導(dǎo)致多個(gè)線程同時(shí)創(chuàng)建實(shí)例。為了解決這個(gè)問(wèn)題,可以在getInstance()
方法中添加線程同步機(jī)制,如使用synchronized
關(guān)鍵字或者雙重檢查鎖定等方式,來(lái)確保在多線程環(huán)境下僅有一個(gè)實(shí)例被創(chuàng)建。
下面再來(lái)說(shuō)多線程單例模式
3.2 餓漢式單例模式
餓漢式單例模式: 在類加載時(shí)就創(chuàng)建實(shí)例,稱為餓漢式。實(shí)現(xiàn)方式是在類內(nèi)部定義一個(gè)私有的靜態(tài)變量,并直接創(chuàng)建實(shí)例賦值給它,然后提供一個(gè)公有的靜態(tài)方法來(lái)獲取該實(shí)例。(快要餓死了,很需要吃東西,所以說(shuō)菜一上來(lái)就立馬開吃,不管你三七二十四)
public class Singleton { private static final Singleton instance = new Singleton(); // 私有構(gòu)造函數(shù) private Singleton() { } public static Singleton getInstance() { return instance; } }
在餓漢式單例模式中,我們將單例對(duì)象的實(shí)例化放在靜態(tài)常量中,并且將構(gòu)造函數(shù)設(shè)為私有,防止外部代碼創(chuàng)建實(shí)例。在類加載時(shí),靜態(tài)常量
instance
就會(huì)被創(chuàng)建,并且通過(guò)公共的靜態(tài)方法getInstance()
返回該實(shí)例。由于實(shí)例在類加載時(shí)就被創(chuàng)建,因此可以保證單例的唯一性。
3.3 多線程的單例模式
3.3.1 同步方法
同步方法(Synchronized Method):在getInstance()
方法上使用synchronized
關(guān)鍵字,確保在同一時(shí)間只有一個(gè)線程可以進(jìn)入方法,從而避免并發(fā)創(chuàng)建多個(gè)實(shí)例。這種方式簡(jiǎn)單易行,但可能存在性能問(wèn)題,因?yàn)槊看握{(diào)用getInstance()
都需要進(jìn)行同步。
public class Singleton { private static Singleton instance; // 私有構(gòu)造函數(shù) private Singleton() { } public synchronized static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
3.3.2 雙重檢查鎖定
雙重檢查鎖定(Double-Checked Locking):使用雙重檢查鎖定機(jī)制,在getInstance()
方法內(nèi)使用synchronized
塊,只在實(shí)例為null
時(shí)才進(jìn)行同步,避免了每次調(diào)用都進(jìn)行同步的開銷。這種方式在多線程環(huán)境下能夠保證線程安全性,同時(shí)也具有較好的性能。
public class Singleton { private static volatile Singleton instance; // 私有構(gòu)造函數(shù) private Singleton() { } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
需要注意的是,這種方式需要將instance變量聲明為
volatile
,以確保在多線程環(huán)境下的可見性和禁止指令重排序。
3.3.3 靜態(tài)內(nèi)部類
靜態(tài)內(nèi)部類(Static Inner Class):利用類的靜態(tài)內(nèi)部類來(lái)實(shí)現(xiàn)單例模式。靜態(tài)內(nèi)部類在首次使用時(shí)加載,且只加載一次,因此保證了線程安全性和延遲加載。
public class Singleton { private Singleton() { // 私有構(gòu)造函數(shù) } private static class SingletonHolder { private static final Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } }
在多線程環(huán)境下,上述實(shí)現(xiàn)方式都能夠確保只有一個(gè)實(shí)例被創(chuàng)建,并提供線程安全的訪問(wèn)。選擇哪種方式取決于具體的需求和性能要求。此外,還可以結(jié)合其他技術(shù),如使用枚舉類型實(shí)現(xiàn)單例,因?yàn)槊杜e類型的實(shí)例是線程安全且唯一的。
需要注意的是,在某些情況下,可能需要權(quán)衡線程安全和性能之間的取舍。在高并發(fā)環(huán)境下,可以考慮使用其他的并發(fā)控制方式,如使用鎖、使用線程安全的并發(fā)容器等來(lái)實(shí)現(xiàn)單例模式。
4、單例模式總結(jié)
單例模式的核心思想是將類的實(shí)例化過(guò)程控制在一個(gè)特定的范圍內(nèi),以確保只有一個(gè)實(shí)例被創(chuàng)建并且全局可訪問(wèn)。這種模式在需要共享資源或避免重復(fù)創(chuàng)建相同對(duì)象的場(chǎng)景中非常有用。
以下是單例模式的一般實(shí)現(xiàn)步驟:
- 將類的構(gòu)造函數(shù)設(shè)為私有,防止外部代碼直接創(chuàng)建實(shí)例。
- 在類內(nèi)部創(chuàng)建一個(gè)私有的靜態(tài)變量來(lái)保存單例實(shí)例。
- 提供一個(gè)公共的靜態(tài)方法來(lái)獲取單例實(shí)例,該方法負(fù)責(zé)實(shí)例的創(chuàng)建和返回。
- 在獲取實(shí)例的方法中,需要考慮線程安全性,確保在多線程環(huán)境下只有一個(gè)實(shí)例被創(chuàng)建。
單例模式的優(yōu)點(diǎn):
- 全局唯一性:確保只有一個(gè)實(shí)例存在,全局范圍內(nèi)可以訪問(wèn)該實(shí)例。
- 節(jié)省資源:避免重復(fù)創(chuàng)建相同的對(duì)象,節(jié)省了系統(tǒng)資源。
- 簡(jiǎn)化調(diào)用:通過(guò)單例模式可以將實(shí)例的管理和控制集中處理,簡(jiǎn)化了代碼的使用和調(diào)用方式。
單例模式缺點(diǎn):
- 隱藏依賴關(guān)系:?jiǎn)卫J?strong>將對(duì)象的創(chuàng)建和使用耦合在一起,使得對(duì)象之間的依賴關(guān)系難以識(shí)別和管理。其他組件或類可能會(huì)依賴單例對(duì)象,從而增加了代碼的復(fù)雜性和耦合度。
- 可測(cè)試性降低:由于單例對(duì)象的全局性質(zhì),可能導(dǎo)致測(cè)試?yán)щy。在單元測(cè)試中,如果依賴于單例對(duì)象的方法或類,可能會(huì)難以模擬和替換實(shí)例,從而影響測(cè)試的可靠性和可維護(hù)性。
- 線程安全問(wèn)題:在多線程環(huán)境下,需要特別注意單例模式的線程安全性。如果實(shí)現(xiàn)不當(dāng),可能導(dǎo)致多個(gè)線程同時(shí)創(chuàng)建實(shí)例,從而破壞了單例的唯一性。需要額外的同步措施來(lái)確保線程安全,這可能會(huì)引入性能開銷。
- 限制擴(kuò)展性:?jiǎn)卫J酵ǔJ?strong>通過(guò)將實(shí)例化邏輯封裝在類內(nèi)部來(lái)實(shí)現(xiàn)的,這限制了對(duì)類的擴(kuò)展性。如果需要擴(kuò)展功能或修改實(shí)例化邏輯,可能需要修改單例類的代碼,從而影響其他代碼的穩(wěn)定性和可維護(hù)性。
- 對(duì)象生命周期管理困難:由于單例對(duì)象的生命周期長(zhǎng)于其他對(duì)象,可能會(huì)導(dǎo)致內(nèi)存泄漏問(wèn)題。一旦單例對(duì)象被創(chuàng)建,它將一直存在于內(nèi)存中,直到應(yīng)用程序結(jié)束或顯式銷毀。在某些情況下,可能難以控制和管理單例對(duì)象的生命周期。
因此,應(yīng)謹(jǐn)慎使用單例模式,并根據(jù)具體需求和設(shè)計(jì)考慮選擇適當(dāng)?shù)膶?shí)現(xiàn)方式,以確保單例的正確性和適用性。
單例模式使用場(chǎng)景:
- 全局資源共享:當(dāng)系統(tǒng)中有多個(gè)模塊或?qū)ο笮枰蚕硗粋€(gè)資源時(shí),可以使用單例模式來(lái)管理該資源,確保只有一個(gè)實(shí)例存在。例如,數(shù)據(jù)庫(kù)連接池、線程池、日志管理器等。
- 配置信息管理:當(dāng)需要全局訪問(wèn)和管理配置信息時(shí),可以使用單例模式來(lái)存儲(chǔ)和獲取配置信息。這樣可以避免重復(fù)讀取配置文件,提高性能和效率。
- 日志記錄器:在需要記錄系統(tǒng)日志的場(chǎng)景下,使用單例模式可以確保日志記錄器的唯一性和全局訪問(wèn)性。通過(guò)單例模式,可以集中管理日志記錄器的配置和輸出。
- 緩存管理:在需要管理全局緩存的場(chǎng)景下,可以使用單例模式來(lái)實(shí)現(xiàn)緩存管理器。單例模式確保只有一個(gè)緩存管理器實(shí)例存在,避免重復(fù)創(chuàng)建和維護(hù)多個(gè)緩存實(shí)例。
- 線程池管理:在多線程環(huán)境中,使用單例模式來(lái)管理線程池可以確保線程池的唯一性和可控性。通過(guò)單例模式,可以統(tǒng)一管理線程池的創(chuàng)建、銷毀和任務(wù)調(diào)度。
- GUI應(yīng)用程序中的窗口管理:在圖形用戶界面(GUI)應(yīng)用程序中,使用單例模式來(lái)管理窗口對(duì)象可以確保每個(gè)窗口只有一個(gè)實(shí)例,方便對(duì)窗口進(jìn)行控制和管理。
以上就是詳解Java設(shè)計(jì)模式之單例模式的詳細(xì)內(nèi)容,更多關(guān)于Java 單例模式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring Cloud學(xué)習(xí)教程之Zuul統(tǒng)一異常處理與回退
Spring Cloud Zuul對(duì)異常的處理整體來(lái)說(shuō)還是比較方便的,流程也比較清晰,下面這篇文章主要給大家介紹了關(guān)于Spring Cloud學(xué)習(xí)教程之Zuul統(tǒng)一異常處理與回退的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-04-04Java?for循環(huán)標(biāo)簽跳轉(zhuǎn)到指定位置的示例詳解
這篇文章主要介紹了Java?for循環(huán)標(biāo)簽跳轉(zhuǎn)到指定位置,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05java進(jìn)行遠(yuǎn)程部署與調(diào)試及原理詳解
這篇文章主要介紹了java進(jìn)行遠(yuǎn)程部署與調(diào)試及原理詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12Sharding JDBC讀寫分離實(shí)現(xiàn)原理及實(shí)例
這篇文章主要介紹了Sharding JDBC讀寫分離實(shí)現(xiàn)原理及實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-12-12IntelliJ?IDEA?2022.1.1創(chuàng)建java項(xiàng)目的詳細(xì)方法步驟
最近安裝了IntelliJ IDEA 2022.1.1,發(fā)現(xiàn)新版本的窗口還有些變化的,所以下面這篇文章主要給大家介紹了關(guān)于IntelliJ?IDEA?2022.1.1創(chuàng)建java項(xiàng)目的詳細(xì)方法步驟,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07淺談java繼承中是否創(chuàng)建父類對(duì)象
下面小編就為大家?guī)?lái)一篇淺談java繼承中是否創(chuàng)建父類對(duì)象。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06java環(huán)境變量的配置方法圖文詳解【win10環(huán)境為例】
這篇文章主要介紹了java環(huán)境變量的配置方法,結(jié)合圖文形式詳細(xì)分析了win10環(huán)境下java環(huán)境變量的配置方法與相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2020-04-04java:提示程序包org.junit不存在時(shí)的解決方案
這篇文章主要介紹了java:提示程序包org.junit不存在時(shí)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11