Java?Swing監(jiān)聽(tīng)器的原理及使用方法舉例
一·什么是事件?
在Java中,“事件”是指用戶(hù)與圖形用戶(hù)界面(GUI)組件交互時(shí)產(chǎn)生的操作,如點(diǎn)擊按鈕或在文本框中輸入內(nèi)容。它是描述這種交互行為的對(duì)象,包含了觸發(fā)該事件的源信息及事件類(lèi)型。Java通過(guò)事件監(jiān)聽(tīng)器接口和事件處理方法來(lái)響應(yīng)這些事件,實(shí)現(xiàn)對(duì)用戶(hù)操作的反饋。事件是Java事件驅(qū)動(dòng)編程模型的核心,支持復(fù)雜的GUI應(yīng)用程序開(kāi)發(fā)。
更加通俗的來(lái)講,餐館的服務(wù)員就是事件監(jiān)聽(tīng)器,你點(diǎn)菜就是事件,而廚師接到消息做菜,就是結(jié)果。
二·Swing的監(jiān)聽(tīng)器有哪些?
1.常用三類(lèi):
(1)MouseListener,MouseMotionListener,MouseWheelListener
MouseListener接口用于處理鼠標(biāo)點(diǎn)擊事件。它定義了五個(gè)方法,用于捕捉鼠標(biāo)的單擊、按下和釋放等動(dòng)作:
void mouseClicked(MouseEvent e):當(dāng)鼠標(biāo)按鈕在組件上被點(diǎn)擊(按下并釋放)時(shí)調(diào)用。void mousePressed(MouseEvent e):當(dāng)鼠標(biāo)按鈕在組件上被按下時(shí)調(diào)用。void mouseReleased(MouseEvent e):當(dāng)鼠標(biāo)按鈕在組件上被釋放時(shí)調(diào)用。void mouseEntered(MouseEvent e):當(dāng)鼠標(biāo)進(jìn)入到組件區(qū)域時(shí)調(diào)用。void mouseExited(MouseEvent e):當(dāng)鼠標(biāo)離開(kāi)組件區(qū)域時(shí)調(diào)用。
MouseMotionListener接口用于監(jiān)聽(tīng)鼠標(biāo)的移動(dòng)以及拖拽事件。它定義了兩個(gè)方法:
void mouseDragged(MouseEvent e):當(dāng)鼠標(biāo)按鍵被按下并且鼠標(biāo)指針在組件上移動(dòng)時(shí)調(diào)用。void mouseMoved(MouseEvent e):當(dāng)鼠標(biāo)指針在組件上移動(dòng)但沒(méi)有按鍵被按下時(shí)調(diào)用。
MouseWheelListener接口用于處理鼠標(biāo)滾輪滾動(dòng)事件。它只有一個(gè)方法:
void mouseWheelMoved(MouseWheelEvent e):當(dāng)鼠標(biāo)滾輪滾動(dòng)時(shí)調(diào)用。可以通過(guò)MouseWheelEvent對(duì)象獲取滾動(dòng)的“刻度”,正數(shù)表示向前滾動(dòng)(向遠(yuǎn)離用戶(hù)的方向),負(fù)數(shù)表示向后滾動(dòng)(向接近用戶(hù)的方向)。
也就是,這三個(gè)幾乎監(jiān)聽(tīng)了所有有關(guān)鼠標(biāo)的行為。點(diǎn)擊,滾動(dòng),進(jìn)入離開(kāi),拖動(dòng),都有它實(shí)現(xiàn)。
(2)KeyListener
KeyListener接口用于監(jiān)聽(tīng)鍵盤(pán)事件。它定義了三個(gè)方法,用于捕捉按鍵被按下、釋放以及鍵入的動(dòng)作:
void keyTyped(KeyEvent e):當(dāng)一個(gè)鍵被按下并且釋放時(shí)調(diào)用。此方法不捕獲像Shift、Ctrl這樣的修飾鍵。void keyPressed(KeyEvent e):當(dāng)一個(gè)鍵被按下時(shí)調(diào)用。void keyReleased(KeyEvent e):當(dāng)一個(gè)鍵被釋放時(shí)調(diào)用。
要使用KeyListener,你需要?jiǎng)?chuàng)建一個(gè)類(lèi)實(shí)現(xiàn)該接口,并根據(jù)需要重寫(xiě)上述方法之一或全部。然后通過(guò)addKeyListener方法將你的監(jiān)聽(tīng)器添加到組件上。需要注意的是,不是所有組件都默認(rèn)獲得焦點(diǎn),因此你可能需要設(shè)置組件為可聚焦或者手動(dòng)請(qǐng)求焦點(diǎn)以確保它可以接收鍵盤(pán)事件。
所以,任何需要鍵盤(pán)操作(比如做個(gè)小游戲),都需要KeyListener。
(3)ActionListener
ActionListener接口主要用于處理動(dòng)作事件,如按鈕點(diǎn)擊。它只有一個(gè)方法:
void actionPerformed(ActionEvent e):當(dāng)一個(gè)指定的操作發(fā)生時(shí)調(diào)用,比如用戶(hù)點(diǎn)擊了一個(gè)按鈕。
為了使用ActionListener,你需要?jiǎng)?chuàng)建一個(gè)類(lèi)實(shí)現(xiàn)ActionListener接口,并重寫(xiě)actionPerformed方法。然后通過(guò)addActionListener方法將你的監(jiān)聽(tīng)器添加到相應(yīng)的組件上,例如按鈕(JButton)。當(dāng)用戶(hù)觸發(fā)了該組件的“動(dòng)作”(例如點(diǎn)擊按鈕),就會(huì)調(diào)用actionPerformed方法。
按鈕JButton點(diǎn)擊實(shí)現(xiàn)需要ActionListener。
三·如何調(diào)用一個(gè)監(jiān)聽(tīng)器?
1.implements Listener/extends Adapter
(1)implements Listener
public class ExampleListener implements KeyListener {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
}
這是最傳統(tǒng)的做法,調(diào)用Listener接口。由于接口的特性,它通常用于一個(gè)監(jiān)聽(tīng)器類(lèi)需要繼承多個(gè)監(jiān)聽(tīng)器的情況。但是由于接口的特性,你需要實(shí)現(xiàn)它所有的方法(空著放著就行)。
(2)extends Adapter
public class ExampleListener extends KeyAdapter {
}
這是新的方式,繼承Adapter類(lèi)。但是由于類(lèi)只支持單繼承,多個(gè)需要實(shí)現(xiàn)的方法只能有一個(gè)這么做。Adapter不再?gòu)?qiáng)行實(shí)現(xiàn)不需要的方法。
2.使用監(jiān)聽(tīng)器
textField.addKeyListener(exampleListener);
它可以被拴在任何一個(gè)JPanel,JButton,JFrame,JTextField,等等,只要有對(duì)應(yīng)的實(shí)現(xiàn)方法就行。
3.保障書(shū)
textField.requestFocus();
隨時(shí)注意,你的監(jiān)聽(tīng)器應(yīng)該被賦予焦點(diǎn)。
四· 總結(jié)與深化理解:事件驅(qū)動(dòng)編程的精髓與Swing監(jiān)聽(tīng)器的本質(zhì)
回顧前文,我們系統(tǒng)地探討了Java GUI編程中“事件”的概念、Swing框架中核心的監(jiān)聽(tīng)器接口及其使用方法?,F(xiàn)在,讓我們站在更高的視角進(jìn)行總結(jié),并深入剖析其背后的設(shè)計(jì)哲學(xué)、運(yùn)行機(jī)制以及在實(shí)際開(kāi)發(fā)中需要注意的關(guān)鍵點(diǎn)。
1. 事件驅(qū)動(dòng)模型:GUI的“生命線”
核心思想: Java GUI(尤其是Swing/AWT)建立在事件驅(qū)動(dòng)編程模型(Event-Driven Programming, EDP) 之上。這與傳統(tǒng)的命令行程序(順序執(zhí)行)或過(guò)程式程序截然不同。在EDP中,程序的執(zhí)行流程主要由用戶(hù)交互(點(diǎn)擊、輸入、移動(dòng)等) 或系統(tǒng)事件(窗口刷新、定時(shí)器觸發(fā)等) 來(lái)驅(qū)動(dòng)。
組件協(xié)作的基石: 事件模型清晰地定義了GUI中各組件的職責(zé)邊界:
事件源(Event Source): 如
JButton,JTextField,JFrame等。它們是用戶(hù)交互的直接對(duì)象,負(fù)責(zé)感知并“產(chǎn)生”事件對(duì)象(如ActionEvent,MouseEvent,KeyEvent)。事件對(duì)象(Event Object): 封裝了事件的詳細(xì)信息(如事件類(lèi)型、發(fā)生時(shí)間、坐標(biāo)位置、按下的鍵碼、涉及的組件等)。它們是事件源傳遞給監(jiān)聽(tīng)器的“消息載體”。
事件監(jiān)聽(tīng)器(Event Listener): 如
ActionListener,MouseListener,KeyListener等。它們是“訂閱”特定事件類(lèi)型的對(duì)象,定義了當(dāng)事件發(fā)生時(shí)應(yīng)該執(zhí)行的邏輯(actionPerformed,mouseClicked,keyPressed等方法)。它們是程序邏輯響應(yīng)的核心。
松耦合設(shè)計(jì): 事件模型最大的優(yōu)勢(shì)在于實(shí)現(xiàn)了松耦合。事件源只需要知道如何注冊(cè)監(jiān)聽(tīng)器和觸發(fā)事件,完全不需要知道具體是哪個(gè)監(jiān)聽(tīng)器在處理事件,更不需要知道處理邏輯的細(xì)節(jié)。監(jiān)聽(tīng)器只需要關(guān)注它感興趣的事件類(lèi)型并實(shí)現(xiàn)相應(yīng)的處理邏輯,不需要關(guān)心事件具體是由哪個(gè)組件產(chǎn)生的(除非需要,可以通過(guò)事件對(duì)象獲?。_@種設(shè)計(jì)極大地提高了代碼的模塊化、可維護(hù)性和可擴(kuò)展性。添加新功能(如新的按鈕響應(yīng))通常只需要添加新的監(jiān)聽(tīng)器并注冊(cè),而無(wú)需修改現(xiàn)有的事件源或其他監(jiān)聽(tīng)器代碼?;氐侥愕牟宛^比喻:顧客(用戶(hù))點(diǎn)菜(產(chǎn)生事件),服務(wù)員(事件源/分發(fā)機(jī)制)只需要記錄訂單(封裝事件)并傳遞給后廚(監(jiān)聽(tīng)器注冊(cè)中心),后廚(監(jiān)聽(tīng)器集合)根據(jù)訂單類(lèi)型(事件類(lèi)型)分配給對(duì)應(yīng)菜系的廚師(具體監(jiān)聽(tīng)器實(shí)現(xiàn))。廚師(具體監(jiān)聽(tīng)器方法)專(zhuān)注于烹飪自己的那道菜(處理邏輯),他不需要知道是哪位顧客點(diǎn)的,也不需要知道其他廚師在做什么;服務(wù)員也不需要知道廚師具體怎么烹飪。整個(gè)流程高效、職責(zé)清晰、易于擴(kuò)展(增加新菜系/廚師)。
2. 監(jiān)聽(tīng)器接口 vs. 適配器類(lèi):選擇之道
接口 (implements Listener):
優(yōu)點(diǎn): 遵循“面向接口編程”原則,提供了最大的靈活性。一個(gè)類(lèi)可以實(shí)現(xiàn)多個(gè)監(jiān)聽(tīng)器接口(如同時(shí)實(shí)現(xiàn)
MouseListener和KeyListener),這在需要處理多種不同類(lèi)型事件的場(chǎng)景中非常有用(例如,一個(gè)復(fù)雜的繪圖組件可能需要同時(shí)響應(yīng)鼠標(biāo)和鍵盤(pán))。缺點(diǎn): 強(qiáng)制要求實(shí)現(xiàn)接口中定義的所有方法,即使你只關(guān)心其中一個(gè)(如
mouseClicked)。對(duì)于方法眾多的接口(如MouseListener有5個(gè)方法),這會(huì)導(dǎo)致代碼中出現(xiàn)大量空方法體({}),顯得冗余和不夠優(yōu)雅。
適配器類(lèi) (extends Adapter):
優(yōu)點(diǎn): 適配器類(lèi)(如
MouseAdapter,KeyAdapter,WindowAdapter)是監(jiān)聽(tīng)器接口的空實(shí)現(xiàn)(所有方法都是空方法體)。當(dāng)你繼承適配器類(lèi)時(shí),你只需要覆蓋(@Override)你真正關(guān)心的那個(gè)或幾個(gè)方法即可。這極大地簡(jiǎn)化了代碼,避免了不必要的空方法體,代碼意圖更加清晰。缺點(diǎn): Java是單繼承語(yǔ)言。一個(gè)類(lèi)只能繼承一個(gè)父類(lèi)。如果你需要繼承一個(gè)業(yè)務(wù)相關(guān)的基類(lèi)(如自定義的
MyBasePanel),同時(shí)又需要使用多個(gè)適配器類(lèi)的功能(如同時(shí)需要MouseAdapter和KeyAdapter),那么適配器類(lèi)的方式就行不通了。此時(shí),只能選擇實(shí)現(xiàn)多個(gè)監(jiān)聽(tīng)器接口。
匿名內(nèi)部類(lèi)與Lambda表達(dá)式: 除了顯式定義實(shí)現(xiàn)類(lèi)或適配器子類(lèi)外,Swing事件處理中大量使用匿名內(nèi)部類(lèi)和(Java 8+)Lambda表達(dá)式來(lái)注冊(cè)監(jiān)聽(tīng)器,特別是對(duì)于簡(jiǎn)單的邏輯。這能顯著減少代碼量,將監(jiān)聽(tīng)器邏輯緊鄰注冊(cè)點(diǎn)。
3. 事件分發(fā)線程(EDT):GUI線程安全的基石
核心概念: Swing組件不是線程安全的。所有對(duì)Swing組件的訪問(wèn)(創(chuàng)建、修改、查詢(xún)狀態(tài))必須在同一個(gè)特定的線程中進(jìn)行,這個(gè)線程稱(chēng)為事件分發(fā)線程(Event Dispatch Thread, EDT)。
為什么需要EDT? 用戶(hù)事件(如鼠標(biāo)點(diǎn)擊、按鍵)由操作系統(tǒng)捕獲并傳遞給Java應(yīng)用程序。Swing框架將這些事件放入一個(gè)事件隊(duì)列(Event Queue) 中。EDT是一個(gè)獨(dú)立的、持續(xù)運(yùn)行的線程,它的唯一任務(wù)就是從事件隊(duì)列中取出事件,并將其分派(
dispatch)給注冊(cè)在對(duì)應(yīng)組件上的監(jiān)聽(tīng)器(調(diào)用監(jiān)聽(tīng)器的方法)。你的actionPerformed,mouseClicked,keyPressed等方法,都是在EDT內(nèi)部被調(diào)用的!黃金法則: 任何修改Swing組件狀態(tài)(如設(shè)置文本
setText(...)、改變背景色setBackground(...)、添加/移除組件add(...)/remove(...))或查詢(xún)其狀態(tài)(如獲取文本getText())的代碼,都必須在EDT上執(zhí)行。后果與風(fēng)險(xiǎn): 如果在EDT之外的線程(如主線程
main、工作線程Thread/Runnable、SwingWorker的工作線程)中直接訪問(wèn)或修改Swing組件,程序的行為將是未定義的:可能看起來(lái)正常工作,也可能出現(xiàn)界面凍結(jié)、顯示錯(cuò)亂、數(shù)據(jù)不一致,甚至拋出難以預(yù)測(cè)的異常。這是Swing開(kāi)發(fā)中最常見(jiàn)、也最隱蔽的Bug來(lái)源之一。如何確保在EDT執(zhí)行?
監(jiān)聽(tīng)器方法內(nèi): 如前所述,監(jiān)聽(tīng)器方法(
actionPerformed等)本身就是在EDT中被調(diào)用的。因此,在這些方法內(nèi)部直接操作Swing組件是安全的。程序啟動(dòng) (main方法): 創(chuàng)建和顯示GUI的代碼(
new JFrame(),frame.setVisible(true))也應(yīng)放在EDT中。標(biāo)準(zhǔn)做法是使用SwingUtilities.invokeLater():后臺(tái)任務(wù)更新UI: 當(dāng)執(zhí)行耗時(shí)操作(如網(wǎng)絡(luò)請(qǐng)求、大文件讀寫(xiě)、復(fù)雜計(jì)算)時(shí),絕對(duì)不能阻塞EDT(否則界面會(huì)凍結(jié))。應(yīng)該使用工作線程(如
Thread,ExecutorService, 或?qū)iT(mén)為Swing設(shè)計(jì)的SwingWorker)執(zhí)行耗時(shí)任務(wù)。當(dāng)任務(wù)完成并需要更新UI時(shí),必須將更新UI的代碼調(diào)度回EDT執(zhí)行:java
// 在工作線程中
SomeResult result = doLongRunningTask();
// 更新UI必須在EDT
SwingUtilities.invokeLater(() -> {
textField.setText(result.toString()); // 安全更新
progressBar.setValue(100);
});SwingWorker提供了更結(jié)構(gòu)化的方式(doInBackground()執(zhí)行任務(wù),done()或process()方法自動(dòng)在EDT中被調(diào)用進(jìn)行UI更新)。
4. 焦點(diǎn)管理:被忽視的關(guān)鍵
焦點(diǎn)的意義: 在GUI中,“焦點(diǎn)(Focus)”表示哪個(gè)組件當(dāng)前接收鍵盤(pán)輸入。只有獲得焦點(diǎn)的組件(如
JTextField,JButton可被空格激活)才能觸發(fā)KeyListener事件。用戶(hù)設(shè)置焦點(diǎn): 用戶(hù)通常通過(guò)鼠標(biāo)點(diǎn)擊(對(duì)于可聚焦組件)或Tab鍵(在可聚焦組件間循環(huán)切換)來(lái)設(shè)置焦點(diǎn)。
程序設(shè)置焦點(diǎn):requestFocus(): 正如你在第三部分“保障書(shū)”中正確指出的,
component.requestFocus()方法用于在代碼中請(qǐng)求將焦點(diǎn)設(shè)置到指定組件。這對(duì)于初始化界面(如讓第一個(gè)輸入框自動(dòng)獲得焦點(diǎn))或在用戶(hù)完成某個(gè)操作后自動(dòng)跳轉(zhuǎn)到下一個(gè)輸入框非常有用。為什么需要 requestFocus()?
初始化: 窗口剛打開(kāi)時(shí),焦點(diǎn)可能不在你期望的組件上。調(diào)用
requestFocus()可以確保關(guān)鍵輸入組件(如登錄名輸入框)立刻可用。操作后引導(dǎo): 例如,用戶(hù)點(diǎn)擊“下一步”按鈕后,程序邏輯可能需要用戶(hù)緊接著在另一個(gè)文本框中輸入。在按鈕的
actionPerformed方法中調(diào)用nextTextField.requestFocus()可以流暢地引導(dǎo)用戶(hù)操作。KeyListener 的必要條件: 這是最關(guān)鍵的!如果一個(gè)組件沒(méi)有獲得焦點(diǎn),它的
KeyListener根本不會(huì)觸發(fā)。如果你發(fā)現(xiàn)鍵盤(pán)事件沒(méi)有響應(yīng),第一件事就是檢查該組件是否獲得了焦點(diǎn)(可以通過(guò)component.hasFocus()判斷),并考慮在適當(dāng)?shù)牡胤秸{(diào)用requestFocus()。例如,在一個(gè)包含多個(gè)輸入框的面板中,你需要點(diǎn)擊某個(gè)文本框使其獲得焦點(diǎn)后,才能在該文本框內(nèi)接收鍵盤(pán)事件。
焦點(diǎn)遍歷策略: Swing提供了
FocusTraversalPolicy來(lái)控制Tab鍵切換焦點(diǎn)的順序。理解默認(rèn)策略和如何自定義策略對(duì)于創(chuàng)建流暢的用戶(hù)體驗(yàn)也很重要。
5. 事件處理的層次結(jié)構(gòu)與事件過(guò)濾
事件傳播: Swing的事件處理機(jī)制具有一定的層次結(jié)構(gòu)。當(dāng)一個(gè)事件(如鼠標(biāo)點(diǎn)擊)發(fā)生在某個(gè)組件上時(shí):
首先,事件會(huì)嘗試在該組件上注冊(cè)的對(duì)應(yīng)類(lèi)型監(jiān)聽(tīng)器中處理。
如果該組件沒(méi)有處理該事件(或者監(jiān)聽(tīng)器沒(méi)有消費(fèi)事件),事件可能會(huì)向上傳播到該組件的父容器。
這個(gè)過(guò)程可以一直持續(xù)到最頂層的窗口(如
JFrame)。
消費(fèi)事件 (consume()): 在監(jiān)聽(tīng)器方法中,可以調(diào)用事件對(duì)象(如
MouseEvent e)的e.consume()方法。這表示該事件已被處理完畢,并阻止其進(jìn)一步向上傳播給父容器。這在需要完全“捕獲”某個(gè)事件,不讓其觸發(fā)父容器可能存在的默認(rèn)行為時(shí)非常有用。JComponent 的特殊方法:
JComponent及其子類(lèi)提供了processXxxEvent()方法(如processMouseEvent(MouseEvent e))和enableEvents(long eventsToEnable)。這些是更低層次的事件處理機(jī)制,允許組件自身處理事件而無(wú)需顯式注冊(cè)監(jiān)聽(tīng)器(內(nèi)部實(shí)現(xiàn)通常還是調(diào)用了監(jiān)聽(tīng)器)。除非有特殊需求(如創(chuàng)建高度定制化的組件),一般推薦使用標(biāo)準(zhǔn)的監(jiān)聽(tīng)器注冊(cè)方式,因其更符合面向?qū)ο蟮脑O(shè)計(jì)原則,代碼更清晰易讀。
五·總結(jié)
盡管Swing在新技術(shù)浪潮中已不再是Java GUI的最前沿,其事件模型體現(xiàn)的設(shè)計(jì)思想和核心概念——事件驅(qū)動(dòng)、松耦合、監(jiān)聽(tīng)器/觀察者模式、線程安全(EDT)、焦點(diǎn)管理——具有永恒的價(jià)值。它們是構(gòu)建任何響應(yīng)式、用戶(hù)友好的交互式應(yīng)用程序的基礎(chǔ)。
深入理解Swing事件模型:
為你維護(hù)和開(kāi)發(fā)遺留Swing應(yīng)用提供了堅(jiān)實(shí)的基礎(chǔ)。
讓你深刻理解了JavaFX等現(xiàn)代GUI框架事件機(jī)制的設(shè)計(jì)動(dòng)機(jī)和優(yōu)勢(shì)所在。
賦予你將“事件驅(qū)動(dòng)”、“觀察者模式”、“線程安全UI更新”等核心概念遷移到其他平臺(tái)(Web前端、Android、桌面跨平臺(tái)框架如JavaFX/SWT、甚至服務(wù)端異步編程)的能力。萬(wàn)變不離其宗,當(dāng)你遇到
addEventListener,setOnClickListener,Observable,subscribe,Channel,Future/Promise等概念時(shí),你會(huì)發(fā)現(xiàn)它們都與你曾經(jīng)在Swing監(jiān)聽(tīng)器上付出的努力有著深刻的內(nèi)在聯(lián)系。
因此,熟練掌握J(rèn)ava Swing的事件處理,絕非僅僅是為了編寫(xiě)一個(gè)過(guò)時(shí)的桌面程序,而是為了掌握一套普適的、強(qiáng)大的、構(gòu)建動(dòng)態(tài)交互世界的思維方式和編程范式。它是你通向更廣闊軟件開(kāi)發(fā)領(lǐng)域的堅(jiān)實(shí)橋梁。在你的技術(shù)生涯中,無(wú)論前端框架如何更迭,移動(dòng)平臺(tái)如何變遷,事件驅(qū)動(dòng)這一核心理念,將始終伴隨著你,助你構(gòu)建流暢、響應(yīng)、用戶(hù)喜愛(ài)的應(yīng)用程序。
到此這篇關(guān)于Java Swing監(jiān)聽(tīng)器的原理及使用方法的文章就介紹到這了,更多相關(guān)Java Swing監(jiān)聽(tīng)器使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中計(jì)算集合中元素的出現(xiàn)次數(shù)統(tǒng)計(jì)
本文主要介紹了Java中計(jì)算集合中元素的出現(xiàn)次數(shù)統(tǒng)計(jì),使用Collections類(lèi)配合HashMap來(lái)統(tǒng)計(jì)和java lamb 計(jì)算這兩種方式,具有一定的參考價(jià)值,感興趣可以了解一下2024-02-02
CommonMark 使用教程:將 Markdown 語(yǔ)法轉(zhuǎn)成 Html
這篇文章主要介紹了CommonMark 使用教程:將 Markdown 語(yǔ)法轉(zhuǎn)成 Html,這個(gè)技巧我們做任何網(wǎng)站都可以用到,而且非常好用。,需要的朋友可以參考下2019-06-06
IDEA中用maven連接數(shù)據(jù)庫(kù)的教程
這篇文章主要介紹了IDEA中用maven連接數(shù)據(jù)庫(kù)的教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11
Maven重復(fù)依賴(lài)問(wèn)題解決(同一個(gè)jar多個(gè)版本)
本文主要介紹了Maven重復(fù)依賴(lài)問(wèn)題解決(同一個(gè)jar多個(gè)版本),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
SpringDataJpa:JpaRepository增刪改查操作
這篇文章主要介紹了SpringDataJpa:JpaRepository增刪改查操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08

