網(wǎng)站怎么做淘寶客網(wǎng)絡(luò)營(yíng)銷的現(xiàn)狀及問題
一、概述
記錄時(shí)間 [2024-08-16]
前置知識(shí):Java 基礎(chǔ)篇;Java 面向?qū)ο?br /> 多線程 01:Java 多線程學(xué)習(xí)導(dǎo)航,線程簡(jiǎn)介,線程相關(guān)概念的整理
多線程 02:線程實(shí)現(xiàn),創(chuàng)建線程的三種方式,通過多線程下載圖片案例分析異同(Thread,Runnable,Callable)
Java 多線程學(xué)習(xí)主要模塊包括:線程簡(jiǎn)介;線程實(shí)現(xiàn);線程控制;線程狀態(tài);線程同步;線程通信問題;拓展高級(jí)主題。
本文是針對(duì)多線程的相關(guān)知識(shí)補(bǔ)充:靜態(tài)代理與 Lambda
表達(dá)式。
文章通過婚慶公司代理婚禮策劃的案例講解了靜態(tài)代理這一模式,并類比了 Thread
類代理 Runnable
接口啟動(dòng)多線程的方式。
此外,文章通過對(duì)內(nèi)部類的簡(jiǎn)化,進(jìn)行 Lambda
表達(dá)式的推導(dǎo),并介紹了 Lambda
表達(dá)式的使用方式和注意點(diǎn),同時(shí)類比 Runnable
接口這個(gè)函數(shù)式接口,講述如何使用 Lambda
表達(dá)式創(chuàng)建 Runnable
對(duì)象。
二、靜態(tài)代理
靜態(tài)代理是一種設(shè)計(jì)模式,常用于 Java 中實(shí)現(xiàn)面向切面編程(AOP)、裝飾者模式等。
在靜態(tài)代理中,代理類是在編譯時(shí)就已經(jīng)定義好的,并且與被代理的對(duì)象具有相同的接口。
代理類可以用來包裝真實(shí)對(duì)象的方法調(diào)用,從而可以在調(diào)用前后添加額外的操作。
1. 基本結(jié)構(gòu)
靜態(tài)代理通常包含以下幾個(gè)部分:
- 接口:定義了真實(shí)對(duì)象和代理對(duì)象都需要實(shí)現(xiàn)的方法。
- 真實(shí)對(duì)象:實(shí)現(xiàn)了接口,提供了實(shí)際業(yè)務(wù)邏輯。
- 代理對(duì)象:也實(shí)現(xiàn)了相同的接口,內(nèi)部包裝了真實(shí)對(duì)象,并在其方法調(diào)用前后添加額外的行為。
2. 案例分析
我們可以使用靜態(tài)代理模式來模擬結(jié)婚與婚慶公司的行為。
在這個(gè)例子中,假設(shè)某人要舉辦一場(chǎng)婚禮,他需要婚慶公司來幫忙安排婚禮策劃的各個(gè)方面。
- 婚禮策劃:看作一個(gè)接口,真實(shí)對(duì)象和代理對(duì)象都需要實(shí)現(xiàn)這個(gè)接口;
- 某人:真實(shí)對(duì)象,結(jié)婚當(dāng)事人;
- 婚慶公司:代理對(duì)象,代理某人,幫忙安排婚禮策劃的各個(gè)方面。
定義接口
首先,我們定義一個(gè) Marry
接口,它表示婚禮策劃服務(wù)。同時(shí)定義一個(gè) HappyMarry()
方法。
interface Marry {// 人間四大喜事// 久旱逢甘霖,他鄉(xiāng)遇故知,洞房花燭夜,金榜題名時(shí)。void HappyMarry();
}
創(chuàng)建真實(shí)對(duì)象
創(chuàng)建一個(gè) Person
類,它代表真實(shí)對(duì)象,需要實(shí)現(xiàn) Marry
接口,并實(shí)現(xiàn)接口中的方法。
// 真實(shí)角色,結(jié)婚當(dāng)事人
class Person implements Marry {@Overridepublic void HappyMarry() {System.out.println("某人要結(jié)婚了,超開心");}
}
創(chuàng)建代理對(duì)象
創(chuàng)建一個(gè) WeddingCompany
類,它是代理角色,幫助目標(biāo)對(duì)象安排婚禮策劃的各個(gè)方面。
代理類也需要實(shí)現(xiàn) Marry
接口,并實(shí)現(xiàn)接口中的方法。
同時(shí),代理類中包裝了一個(gè)真實(shí)的 Marry
對(duì)象。代理類將在計(jì)劃婚禮前后添加額外的行為,比如咨詢、準(zhǔn)備和清理工作。
- 婚禮之前,布置現(xiàn)場(chǎng);
- 婚禮之后,清理工作。
// 代理角色,幫助目標(biāo)對(duì)象安排婚禮策劃的各個(gè)方面
class WeddingCompany implements Marry {// 包裝一個(gè)真實(shí)的結(jié)婚對(duì)象private Marry target;public WeddingCompany(Marry target) {this.target = target;}@Overridepublic void HappyMarry() {before();// 實(shí)際上是某人要結(jié)婚this.target.HappyMarry();after();}private void before() {System.out.println("婚禮之前,布置現(xiàn)場(chǎng)");}private void after() {System.out.println("婚禮之后,清理工作");}}
使用代理對(duì)象
最后,我們?cè)谥鞒绦蛑惺褂么韺?duì)象來調(diào)用 HappyMarry()
方法。
在代理對(duì)象中傳入真實(shí)對(duì)象,然后調(diào)用方法。
public class WeddingDemo {public static void main(String[] args) {// 真實(shí)對(duì)象Person person = new Person();// 代理對(duì)象WeddingCompany proxy = new WeddingCompany(person);// // 代理對(duì)象調(diào)用方法proxy.HappyMarry();// 合起來寫// new WeddingCompany(new Person()).HappyMarry();}
}
輸出結(jié)果
當(dāng)運(yùn)行 WeddingDemo
類時(shí),輸出應(yīng)該是這樣的:
婚禮之前,布置現(xiàn)場(chǎng)
某人要結(jié)婚了,超開心
婚禮之后,清理工作
3. 注意事項(xiàng)
靜態(tài)代理模式總結(jié):
- 真實(shí)對(duì)象和代理對(duì)象都要實(shí)現(xiàn)同一個(gè)接口;
- 代理對(duì)象要代理真實(shí)角色。
靜態(tài)代理模式的優(yōu)點(diǎn):
- 代理對(duì)象可以做很多真實(shí)對(duì)象做不了的事情;
- 真實(shí)對(duì)象專注做自己的事情。
4. 類比多線程代理
在 Java 中,通過 Thread
類代理 Runnable
接口啟動(dòng)多線程是一種常見的模式。
這種模式類似于靜態(tài)代理模式,這里的代理行為由 Thread
類完成的。
在這個(gè)模式中,Thread
類扮演了代理的角色,它代理了 Runnable
接口的實(shí)現(xiàn),并且負(fù)責(zé)啟動(dòng)線程。我們可以將 Thread
類看作是代理類,它包裝了一個(gè)實(shí)現(xiàn)了 Runnable
接口的對(duì)象,并在適當(dāng)?shù)臅r(shí)機(jī)調(diào)用其run()
方法。
- 接口:
Runnable
接口,定義了線程執(zhí)行的行為。 - 真實(shí)對(duì)象:實(shí)現(xiàn)了
Runnable
接口的類,提供了實(shí)際要執(zhí)行的任務(wù)。 - 代理對(duì)象:
Thread
類,它代理了Runnable
接口的實(shí)現(xiàn),并負(fù)責(zé)啟動(dòng)和管理線程。
例如:
// lambda 表達(dá)式
new Thread( ()-> System.out.println("線程") ).start();
三、Lambda 表達(dá)式
Lambda
表達(dá)式是 Java 8 引入的一項(xiàng)重要功能,它允許定義簡(jiǎn)潔的一次性使用的函數(shù)。
Lambda
表達(dá)式簡(jiǎn)化了代碼的編寫,通常用于實(shí)現(xiàn)函數(shù)式接口(只有一個(gè)抽象方法的接口)。
對(duì)于函數(shù)式接口,可以通過 Lambda
表達(dá)式來創(chuàng)建該接口的對(duì)象。
1. 基本概念
語法格式
Lambda
表達(dá)式的語法格式如下:
parameters
:參數(shù)列表。->
:箭頭符號(hào),表示參數(shù)列表之后跟著的是主體部分。expression
或{ statements; }
:主體部分,可以是一個(gè)表達(dá)式或一組語句。
(parameters) -> expression// 或者
(parameters) -> {statements; // statements2;
}
參數(shù)
無參數(shù)的 Lambda
表達(dá)式:
// () -> System.out.println("Hello, Lambda!");
Runnable task = () -> System.out.println("Hello, Lambda!");
task.run();
單參數(shù)的 Lambda
表達(dá)式:
// (int a) -> System.out.println("Hello, Lambda!" + a);
Runnable task = (int a) -> System.out.println("Hello, Lambda!" + a);
task.run();
多參數(shù)的 Lambda
表達(dá)式:
// (int a, int b) -> System.out.println("...");
Runnable task = (int a, int b) -> System.out.println("Hello, Lambda!" + a);
task.run();
注意事項(xiàng)
Lambda
表達(dá)式使用前提:接口為函數(shù)式接口。- 如果
Lambda
表達(dá)式的主體部分只有一個(gè)表達(dá)式,可以不用{}
包裹;多行代碼需要用{}
包裹,表示為一個(gè)整體的代碼塊。 - 如果
Lambda
表達(dá)式的參數(shù)列表中只有一個(gè)參數(shù)時(shí),括號(hào)、參數(shù)類型可以省略。例如,(int a)
可以簡(jiǎn)化成a
。 - 有多個(gè)參數(shù)時(shí),必須加括號(hào),但可以同時(shí)省略參數(shù)類型。例如,
(int a, int b, int c)
可以簡(jiǎn)化成(a, b, c)
。
優(yōu)點(diǎn)
以下是使用 Lambda
表達(dá)式的幾個(gè)主要原因:
- 代碼簡(jiǎn)潔性。用更少的代碼實(shí)現(xiàn)相同的功能。
- 避免內(nèi)部類定義過多。
- 減少了不必要的樣板代碼,只留下核心的邏輯。
例如,可以用一行代碼定義一個(gè)方法,而不是寫一個(gè)完整的內(nèi)部類。
傳統(tǒng)的內(nèi)部類方式:
Runnable task = new Runnable() {@Overridepublic void run() {System.out.println("Hello, Lambda!");}
};
使用 Lambda
表達(dá)式:
Runnable task = () -> System.out.println("Hello, Lambda!");
2. 推導(dǎo)過程
接下來,我們通過對(duì)內(nèi)部類的簡(jiǎn)化,進(jìn)行 Lambda
表達(dá)式的推導(dǎo)。
定義函數(shù)式接口
定義一個(gè)函數(shù)式接口 ILike
,它只有一個(gè)抽象方法 lambda()
。
// 1. 定義一個(gè)函數(shù)式接口
interface ILike {// 函數(shù)式編程,有且僅有一個(gè)抽象方法public abstract void lambda();
}
外部類實(shí)現(xiàn)接口
定義一個(gè) Like
類去實(shí)現(xiàn) ILike
接口。
// 2. 實(shí)現(xiàn)類(外部):定義一個(gè)類去實(shí)現(xiàn)接口
class Like implements ILike {// 實(shí)現(xiàn)接口的抽象方法@Overridepublic void lambda() {System.out.println("Test Lambda Like...");}
}// 主方法中
ILike like = new Like();
like.lambda();
靜態(tài)內(nèi)部類實(shí)現(xiàn)
簡(jiǎn)化:定義一個(gè)靜態(tài)內(nèi)部類 Like2
去實(shí)現(xiàn) ILike
接口。
// 3. 靜態(tài)內(nèi)部類
static class Like2 implements ILike {// 實(shí)現(xiàn)接口的抽象方法@Overridepublic void lambda() {System.out.println("Test Lambda Like2...");}
}// 主方法中
like = new Like2();
like.lambda();
局部?jī)?nèi)部類實(shí)現(xiàn)
簡(jiǎn)化:定義一個(gè)局部?jī)?nèi)部類 Like3
去實(shí)現(xiàn) ILike
接口。
// 4. 局部(成員)內(nèi)部類
class Like3 implements ILike {// 實(shí)現(xiàn)接口的抽象方法@Overridepublic void lambda() {System.out.println("Test Lambda Like3...");}
}// 主方法中
like = new Like3();
like.lambda();
匿名內(nèi)部類實(shí)現(xiàn)
簡(jiǎn)化:定義一個(gè)匿名內(nèi)部類去實(shí)現(xiàn) ILike
接口。
// 5. 匿名內(nèi)部類,沒有名稱的類,必須借助接口或者父類
like = new ILike() {@Overridepublic void lambda() {System.out.println("Test Lambda Like4...");}
};like.lambda();
用 Lambda 表達(dá)式簡(jiǎn)化
用 Lambda
表達(dá)式進(jìn)行簡(jiǎn)化。一個(gè)簡(jiǎn)化的過程,只保留最核心的代碼。
// 6. 用 Lambda 表達(dá)式進(jìn)行簡(jiǎn)化
// 一個(gè)簡(jiǎn)化的過程,只保留最核心的代碼like = ()-> {System.out.println("Test Lambda Like5...");
};like.lambda();
3. 類比 Runnable 接口
Runnable
接口定義:
public interface Runnable {public abstract void run();
}
在 Java 中,函數(shù)式接口是指一個(gè)接口中只定義了一個(gè)抽象方法的接口。
Runnable
接口中只包含一個(gè)抽象方法 run()
,符合這個(gè)定義。因而 Runnable
接口是一個(gè)函數(shù)式接口,可以被 Lambda
表達(dá)式所使用。
使用 Lambda
表達(dá)式創(chuàng)建 Runnable
對(duì)象:
// Runnable task = () -> System.out.println("Hello, Runnable!");public class RunnableExample {public static void main(String[] args) {// 使用 Lambda 表達(dá)式創(chuàng)建 Runnable 對(duì)象Runnable task = () -> System.out.println("Hello, Runnable!");// 創(chuàng)建 Thread 對(duì)象,并傳入 Runnable 對(duì)象Thread thread = new Thread(task);// 啟動(dòng)線程thread.start();}
}
四、參考資料
狂神說 Java 多線程:https://www.bilibili.com/video/BV1V4411p7EF
TIOBE 編程語言走勢(shì): https://www.tiobe.com/tiobe-index/
Typora 官網(wǎng):https://www.typoraio.cn/
Oracle 官網(wǎng):https://www.oracle.com/
Notepad++ 下載地址:https://notepad-plus.en.softonic.com/
IDEA 官網(wǎng):https://www.jetbrains.com.cn/idea/
Java 開發(fā)手冊(cè):https://developer.aliyun.com/ebook/394
Java 8 幫助文檔:https://docs.oracle.com/javase/8/docs/api/
MVN 倉庫:https://mvnrepository.com/