行為參數(shù)化
行為參數(shù)化:就是可以幫助你處理頻繁變更的需求的一種軟件開發(fā)模式来氧。
==一言蔽之,它意味著拿出一個(gè)代碼塊驾诈,先把它準(zhǔn)備好確不去執(zhí)行它。這個(gè)代碼塊以后可以被你的程序的其它部分調(diào)用反症,這意味著你可以推遲這塊代碼的執(zhí)行。==
例如:你可以將==代碼塊作為參數(shù)==傳遞給==另一個(gè)方法==砾隅,==稍后再去執(zhí)行它==漠另。這樣這個(gè)方法的行為就是基于代碼被參數(shù)化了漆改。
準(zhǔn)備工作
public class Apple {
private Integer id;
private String color;
private Integer weight;
}
需求1
比如:商家為了賣蘋果俘枫,為了了解自己商品(蘋果)的庫存钟病,需要查找?guī)齑嫠屑t色的蘋果功能。
解決方案如下:
public class LambdaDemo01 {
public static List<Apple> filterAppleColor(List<Apple> allApples) {
//1 : 準(zhǔn)備一個(gè)容器用來存儲(chǔ)篩選出紅色蘋果的集合
List<Apple> resultList = new ArrayList<>();
//2 : 通過循環(huán)從庫存中allApples去比對(duì)屬于紅色蘋果的數(shù)據(jù)
for (Apple allApple : allApples) {
// 3: 比對(duì)紅色的蘋果數(shù)據(jù)
if(allApple.getColor().equals("紅色")){
//4 : 然后添加到resultList容器中
resultList.add(allApple);
}
}
return resultList;
}
public static void main(String[] args) {
// 1暇番、蘋果庫存
List<Apple> apples = new ArrayList<>();
apples.add(new Apple(1, "紅色", 200));
apples.add(new Apple(2, "綠色", 100));
apples.add(new Apple(3, "紅色", 134));
apples.add(new Apple(4, "淺紅色", 400));
apples.add(new Apple(5, "淺綠色", 220));
// 2: 查詢紅色蘋果
List<Apple> appleList = filterAppleColor(apples);
appleList.forEach(System.out::println);
}
}
結(jié)果
Apple{id=1, color='紅色', weight=200}
Apple{id=3, color='紅色', weight=134}
通過上面的第二步嗤放,就是篩選紅色蘋果的所需的條件,現(xiàn)在商家改變了注意了壁酬,他現(xiàn)在還想找到綠色
,你該怎么做呢恨课?簡單的辦法就是把代碼復(fù)制一份這個(gè)方法舆乔,把方法的名字改成filterGreenApple即可,然后修改if的條件來匹配綠色
public class LambdaDemo01 {
public static List<Apple> filterAppleColor(List<Apple> allApples) {
//1 : 準(zhǔn)備一個(gè)容器用來存儲(chǔ)篩選出紅色蘋果的集合
List<Apple> resultList = new ArrayList<>();
//2 : 通過循環(huán)從庫存中allApples去比對(duì)屬于紅色蘋果的數(shù)據(jù)
for (Apple allApple : allApples) {
// 3: 比對(duì)紅色的蘋果數(shù)據(jù)
if(allApple.getColor().equals("紅色")){
//4 : 然后添加到resultList容器中
resultList.add(allApple);
}
}
return resultList;
}
public static List<Apple> filterGreenApple(List<Apple> allApples) {
//1 : 準(zhǔn)備一個(gè)容器用來存儲(chǔ)篩選出綠色蘋果的集合
List<Apple> resultList = new ArrayList<>();
//2 : 通過循環(huán)從庫存中allApples去比對(duì)屬于綠色蘋果的數(shù)據(jù)
for (Apple allApple : allApples) {
// 3: 比對(duì)綠色的蘋果數(shù)據(jù)
if(allApple.getColor().equals("綠色")){
//4 : 然后添加到resultList容器中
resultList.add(allApple);
}
}
return resultList;
}
public static void main(String[] args) {
// 1剂公、蘋果庫存
List<Apple> apples = new ArrayList<>();
apples.add(new Apple(1, "紅色", 200));
apples.add(new Apple(2, "綠色", 100));
apples.add(new Apple(3, "紅色", 134));
apples.add(new Apple(4, "淺紅色", 400));
apples.add(new Apple(5, "淺綠色", 220));
// 2: 查詢綠色蘋果
List<Apple> appleList = filterGreenApple(apples);
appleList.forEach(System.out::println);
}
}
然后如果商家想要篩選更多顏色:暗紅色希俩、黃色、淺綠色等纲辽,這樣實(shí)現(xiàn)起來就非常的臃腫和累贅颜武,怎么解決呢璃搜?==行為參數(shù)化==
第一次優(yōu)化:把顏色當(dāng)做參數(shù)
一種做法就是給方法增加一個(gè)參數(shù),把顏色變成參數(shù)鳞上,這樣就能靈活地使用變化了
public class LambdaDemo02 {
public static List<Apple> filterAppleColor(List<Apple> allApples,String color) {
//1 : 準(zhǔn)備一個(gè)容器用來存儲(chǔ)篩選出紅色蘋果的集合
List<Apple> resultList = new ArrayList<>();
//2 : 通過循環(huán)從庫存中allApples去比對(duì)屬于紅色蘋果的數(shù)據(jù)
for (Apple allApple : allApples) {
// 3: 比對(duì)紅色的蘋果數(shù)據(jù)
if(allApple.getColor().equals(color)){
//4 : 然后添加到resultList容器中
resultList.add(allApple);
}
}
return resultList;
}
public static void main(String[] args) {
// 1这吻、蘋果庫存
List<Apple> apples = new ArrayList<>();
apples.add(new Apple(1, "紅色", 200));
apples.add(new Apple(2, "綠色", 100));
apples.add(new Apple(3, "紅色", 134));
apples.add(new Apple(4, "淺紅色", 400));
apples.add(new Apple(5, "淺綠色", 220));
// 2: 查詢紅色蘋果
List<Apple> appleList = filterAppleColor(apples,"紅色");
List<Apple> appleList2 = filterAppleColor(apples,"綠色");
List<Apple> appleList3 = filterAppleColor(apples,"淺紅色");
System.out.println("--------------紅色------------");
appleList.forEach(System.out::println);
System.out.println("--------------綠色------------");
appleList2.forEach(System.out::println);
System.out.println("--------------淺紅色------------");
appleList3.forEach(System.out::println);
}
}
通過上面,是不是簡單多了
需求2
如果這個(gè)時(shí)候商家又說:要是能區(qū)分重量不一的蘋果該多好呀篙议?
作為軟件工程師的我們唾糯,你可能早就提前做了預(yù)謀,可能商家要改需求鬼贱,可能會(huì)增加重量的過濾移怯,于是你揮揮灑灑的寫下如下可歌可泣的代碼:
public class LambdaDemo02 {
/**
* 過濾某顏色蘋果
*
* @param appleList
* @return
*/
public static List<Apple> filterAppleColor(List<Apple> appleList,String color) {
List<Apple> resultList = new ArrayList<>();
for (Apple apple : appleList) {
if (apple.getColor().equals(color)) {
resultList.add(apple);
}
}
return resultList;
}
/**
* 過濾重量蘋果
*
* @param appleList
* @return
*/
public static List<Apple> filterAppleWeigth(List<Apple> appleList,Integer weight) {
List<Apple> resultList = new ArrayList<>();
for (Apple apple : appleList) {
if (apple.getWeight().equals(weight)) {
resultList.add(apple);
}
}
return resultList;
}
public static void main(String[] args) {
// 1、蘋果庫存
List<Apple> apples = new ArrayList<>();
apples.add(new Apple(1, "紅色", 200));
apples.add(new Apple(2, "綠色", 100));
apples.add(new Apple(3, "紅色", 134));
apples.add(new Apple(4, "淺紅色", 400));
apples.add(new Apple(5, "淺綠色", 220));
// 2这难、過濾紅色蘋果
List<Apple> resultList1 = filterAppleColor(apples,"紅色");
System.out.println("==============紅色==================");
resultList1.forEach(System.out::println);
// 3舟误、過濾綠色蘋果
List<Apple> resultList2 = filterAppleColor(apples,"綠色");
System.out.println("==============綠色==================");
resultList2.forEach(System.out::println);
// 4: 過濾重量超過200g的蘋果
List<Apple> weightList = filterAppleWeigth(apples, 200);
System.out.println("==============重量200g==================");
weightList.forEach(System.out::println);
}
}
這個(gè)時(shí)候,你不由的驚呼道姻乓,我太牛了嵌溢,我實(shí)現(xiàn)了!L侨ā堵腹!
你有沒有發(fā)現(xiàn),這個(gè)代碼確實(shí)比之前的更加高級(jí)了星澳,但是還是沒解決根本性的問題疚顷,如果這個(gè)時(shí)候我還篩選更多的屬性條件,這個(gè)時(shí)候是不是令人有點(diǎn)失望禁偎,因?yàn)槟阌忠煌5闹貜?fù)這個(gè)行為和動(dòng)作腿堤。
如果你想要改變篩選遍歷方式來提升性能,那就得修改所有方法的實(shí)現(xiàn)如暖,而不是改一個(gè)笆檀。從工程的工作量來看,這代價(jià)太大了盒至。
第二天酗洒,商家可能需求就發(fā)生了改變了,我還想找出所有重量超過200g的蘋果枷遂。
如下:
public class LambdaDemo03 {
/**
* 需求2:第二天樱衷,商家可能需求就發(fā)生了改變了,我還想找出所有重量超過200g的蘋果酒唉。
* 真是的需求:查找?guī)齑嫠屑t色的蘋果功能矩桂。
* @param allApples
* @return
*/
public static List<Apple> filterAppleWeight(List<Apple> allApples,int weight) {
//1 : 準(zhǔn)備一個(gè)容器用來存儲(chǔ)篩選出紅色蘋果的集合
List<Apple> resultList = new ArrayList<>();
//2 : 通過循環(huán)從庫存中allApples去比對(duì)屬于紅色蘋果的數(shù)據(jù)
for (Apple allApple : allApples) {
// 3: 比對(duì)紅色的蘋果數(shù)據(jù)
if(allApple.getWeight() > weight){
//4 : 然后添加到resultList容器中
resultList.add(allApple);
}
}
return resultList;
}
public static void main(String[] args) {
// 1、蘋果庫存
List<Apple> apples = new ArrayList<>();
apples.add(new Apple(1, "紅色", 200));
apples.add(new Apple(2, "綠色", 100));
apples.add(new Apple(3, "紅色", 134));
apples.add(new Apple(4, "淺紅色", 400));
apples.add(new Apple(5, "淺綠色", 220));
// 2: 查詢蘋果超過200g的數(shù)據(jù)
List<Apple> appleList = filterAppleWeight(apples,200);
System.out.println("--------------查詢蘋果超過200g的數(shù)據(jù)------------");
appleList.forEach(System.out::println);
}
}
第二次優(yōu)化:一個(gè)方法統(tǒng)一實(shí)現(xiàn)多個(gè)功能
public class LambdaDemo04 {
/**
* 通過flag判斷是通過顏色過濾
* flag=true 顏色過濾
* flag=false 重量過濾
*
* @param appleList
* @return
*/
public static List<Apple> filterAppleColorAndWeigth(List<Apple> appleList,String color,int weight,boolean flag) {
List<Apple> resultList = new ArrayList<>();
for (Apple apple : appleList) {
if ((flag && apple.getColor().equals(color)) || (!flag && apple.getWeight().equals(weight))) {
resultList.add(apple);
}
}
return resultList;
}
public static void main(String[] args) {
// 1痪伦、蘋果庫存
List<Apple> apples = new ArrayList<>();
apples.add(new Apple(1, "紅色", 200));
apples.add(new Apple(2, "綠色", 100));
apples.add(new Apple(3, "紅色", 134));
apples.add(new Apple(4, "淺紅色", 400));
apples.add(new Apple(5, "淺綠色", 220));
// 2侄榴、過濾紅色蘋果
List<Apple> resultList1 = filterAppleColorAndWeigth(apples,"紅色",200,true);
System.out.println("==============紅色==================");
resultList1.forEach(System.out::println);
// 3雹锣、過濾綠色蘋果
List<Apple> resultList2 = filterAppleColorAndWeigth(apples,"綠色",200,false);
System.out.println("==============綠色==================");
resultList2.forEach(System.out::println);
}
}
上面的代碼,看起來確實(shí)挺優(yōu)化的癞蚕,可以一個(gè)方法解決兩個(gè)問題蕊爵,但是這閱讀性太差了,而且不方便維護(hù)涣达。
- true / false 是什么意思呢在辆?
- 此外如果要解決更多變化和需求,比如大小度苔,形狀匆篓,場地,又該怎么辦呢寇窑?估計(jì)會(huì)有很多的filterxxxxx方法吧鸦概!
第三次優(yōu)化:行為參數(shù)化
通過前面已經(jīng)看到,你需要一種比添加很多參數(shù)更好的方法來應(yīng)對(duì)變化的需求甩骏。讓你把代碼往更高層次進(jìn)行重構(gòu)和封裝怎么買做呢窗市?。如下
- 方法的標(biāo)準(zhǔn)建模
什么是標(biāo)準(zhǔn)建模呢饮笛?
就是用面向?qū)ο蟮姆绞剑航涌诨刹臁6x一個(gè)接口來對(duì)選擇進(jìn)行標(biāo)準(zhǔn)建模如下:
定義接口:
public interface ApplePredicate {
boolean test(Apple apple);
}
采用多實(shí)現(xiàn)的方式,代表不同的選擇標(biāo)準(zhǔn)如下:
顏色實(shí)現(xiàn):
public class ApplePredicateColor implements ApplePredicate {
public boolean test(Apple apple) {
return apple.getColor().equals("紅色");
}
}
重量實(shí)現(xiàn):
public class ApplePredicateWeigth implements ApplePredicate {
public boolean test(Apple apple) {
return apple.getWeight() > 200;
}
}
測(cè)試
public class LambdaDemo01 {
// 入?yún)榻涌陬愋停篈ppPredicate福青,方便向下兼容
public static List<Apple> filterAppleColorAndWeigth(List<Apple> appleList,AppPredicate predicate) {
List<Apple> resultList = new ArrayList<>();
for (Apple apple : appleList) {
if (predicate.test(apple)) {
resultList.add(apple);
}
}
return resultList;
}
public static void main(String[] args) {
// 1摄狱、蘋果庫存
List<Apple> apples = new ArrayList<>();
apples.add(new Apple(1, "紅色", 200));
apples.add(new Apple(2, "綠色", 100));
apples.add(new Apple(3, "紅色", 134));
apples.add(new Apple(4, "淺紅色", 400));
apples.add(new Apple(5, "淺綠色", 220));
apples.add(new Apple(6, "紅色", 210));
// 2、過濾紅色蘋果
List<Apple> resultList1 = filterAppleColorAndWeigth(apples,new AppPredicateColor());
System.out.println("==============紅色==================");
resultList1.forEach(System.out::println);
// 3无午、重量200g的蘋果
List<Apple> resultList2 = filterAppleColorAndWeigth(apples,new AppPredicateWeight());
System.out.println("==============重量200g的蘋果==================");
resultList2.forEach(System.out::println);
// 3媒役、重量200g的蘋果 并且是紅色的
List<Apple> resultList3= filterAppleColorAndWeigth(apples,new AppPredicateWeightColor());
System.out.println("==============重量200g的蘋果 并且是紅色的==================");
resultList3.forEach(System.out::println);
}
}
通上面的方式,我把相同邏輯業(yè)務(wù)用接口進(jìn)行定義方法宪迟,然后各種子類去去實(shí)現(xiàn)酣衷,在調(diào)用的過程中去選擇和匹配對(duì)應(yīng)的算法。稱之為:==“策略者模式”==
策略者模式其實(shí)就是:它讓你定義一族算法次泽,把它們封裝起來(稱之為:策略)穿仪,然后在運(yùn)行時(shí)選擇一個(gè)算法,在這里意荤。算法族就是:ApplePredicate牡借,這里的ApplePredicateWeigth、ApplePredicateColor就是它的不同策略袭异。
通過上面,其實(shí)我們已經(jīng)做了意見很酷的事情炬藤,我們只需要傳遞接口的引用對(duì)象御铃,就可以達(dá)到不同的過濾效果碴里,達(dá)到了設(shè)計(jì)模式的要求,對(duì)內(nèi)修改關(guān)閉上真,對(duì)外修改擴(kuò)展咬腋。換句話說:filterXXXX方法的行為被參數(shù)化了。也就是行為參數(shù)化的過程睡互。
小結(jié)
以后在開發(fā)中根竿,如果調(diào)用任何一個(gè)方法,如果這個(gè)方法中有傳遞了接口或者抽象類作為參數(shù)就珠,說明你這個(gè)方法肯定的有一部分邏輯肯定要延遲的外部來執(zhí)行寇壳。我們把這種行為成為:行為參數(shù)化。
策略模式缺陷
目前妻怎,當(dāng)要把新的行為傳遞給filterxxx方法的時(shí)候壳炎,你不得不申明好幾個(gè)或者若干個(gè)ApplePredicate的實(shí)現(xiàn)類,這真的很啰嗦和很費(fèi)時(shí)間逼侦。怎么拯救它呢匿辩?
答案就是:Java的匿名內(nèi)部類。匿名內(nèi)部類可以讓你==同時(shí)申明和實(shí)例化一個(gè)類(接口榛丢,抽象類)==铲球。它可以改善上面的代碼。讓它變得更加的簡潔晰赞。但是我們通過下面的學(xué)習(xí)稼病,匿名內(nèi)部類確實(shí)可以簡化,但是也不完全令人滿意宾肺,因?yàn)橛懈玫姆绞骄褪莏dk1.8引入的Lamdba表達(dá)式溯饵。
匿名內(nèi)部類
第四次優(yōu)化:匿名內(nèi)部類
匿名內(nèi)部類:可以使你的代碼更加簡潔,你可以在定義一個(gè)類(接口锨用,抽象類)的同時(shí)對(duì)其進(jìn)行實(shí)例化丰刊。它與局部類很相似,不同的是它沒有類名增拥,如果某個(gè)局部類你只需要用一次啄巧,那么你就可以使用匿名內(nèi)部類
換句話說:匿名內(nèi)部類是一種允許你==隨建隨用==創(chuàng)建對(duì)象和覆蓋行為方法的一種機(jī)制。
public class ApplePredicateTest {
/**
* 行為參數(shù)化
* @param appleList
* @param predicate 接口
* @return
*/
public static List<Apple> filterApple(List<Apple> appleList, ApplePredicate predicate){
List<Apple> resultList = new ArrayList<>();
for (Apple apple : appleList) {
// 調(diào)用ApplePredicate子類的具體行為
if (predicate.test(apple)) {
resultList.add(apple);
}
}
return resultList;
}
public static void main(String[] args) {
// 1掌栅、蘋果庫存
List<Apple> apples = new ArrayList<>();
apples.add(new Apple(1, "紅色", 200));
apples.add(new Apple(2, "綠色", 100));
apples.add(new Apple(3, "紅色", 134));
apples.add(new Apple(4, "淺紅色", 400));
apples.add(new Apple(5, "淺綠色", 220));
// 2秩仆、使用匿名內(nèi)部類過濾紅色蘋果
List<Apple> resultList1 = filterApple(apples, new ApplePredicate() {
// 具體內(nèi)部類行為動(dòng)作
@Override
public boolean test(Apple apple) {
return apple.getColor().equals("紅色");
}
});
System.out.println("==============紅色==================");
resultList1.forEach(System.out::println);
// 3、使用匿名內(nèi)部類過濾總量超過200g
List<Apple> resultList2 = filterApple(apples, new ApplePredicate() {
// 具體內(nèi)部類行為動(dòng)作
@Override
public boolean test(Apple apple) {
return apple.getWeight() > 200;
}
});
System.out.println("==============重量大于200g==================");
resultList2.forEach(System.out::println);
}
}
是不是體現(xiàn)出了他的:隨建隨用的效果呢猾封?太棒了澄耍。
經(jīng)典的匿名內(nèi)部類謎題
public class Anonymous {
public final int value = 4;
public void doIt(){
int value = 6;
Runnable runnable = new Runnable() {
public final int value = 5;
@Override
public void run() {
int value = 10;
System.out.println(this.value);
}
};
runnable.run();
}
public static void main(String[] args) {
Anonymous anonymous = new Anonymous();
anonymous.doIt();
}
}
答案是:5
通過Debug可以看出來,當(dāng)前this對(duì)象指的是當(dāng)前內(nèi)部類對(duì)象中的value值,如果把this給去了齐莲,那就是當(dāng)前方法里面的值痢站。
匿名內(nèi)部類的理解
- 使用匿名內(nèi)部類:起到保護(hù)和安全的作用。
- 匿名內(nèi)部類:是一種允許你==隨建隨用==創(chuàng)建對(duì)象和覆蓋行為方法的一種機(jī)制选酗≌竽眩可以解決在開發(fā)中需求不停變化的問題。
- 我舉個(gè)例子:在開發(fā)中如果客戶提供不同的需求芒填,傳統(tǒng)的方式是通過接口擴(kuò)展子類進(jìn)行實(shí)現(xiàn)呜叫,但是需求變化如果太多,我們就定義很多的實(shí)現(xiàn)類殿衰,這樣給后續(xù)的維護(hù)和擴(kuò)展都提供了不便朱庆,如果業(yè)務(wù)組合的需求過多,子類也就越多播玖,就越來越不靈活椎工。我們可以利用匿名內(nèi)部類的的隨建隨用的機(jī)制很好的解決子類過多和需求變化過多的情況,廣泛應(yīng)用在比如:jdbctempalte的增刪改查中蜀踏,GUI维蒙,Swing事件行為中,以及stream流中比如:filter,map,sorted方法中果覆,以及底層源碼都可以看到匿名內(nèi)部類的身影颅痊。
- 其實(shí)也它就是在定義一個(gè)類(接口,抽象類)的同時(shí)對(duì)其進(jìn)行實(shí)例化局待。實(shí)例化的每一次都會(huì)在當(dāng)前類下生成一個(gè)==當(dāng)前類$count的類==斑响,這個(gè)類也就就是匿名類的具體類的實(shí)現(xiàn),可以在target目錄下可以看到钳榨。如果實(shí)例化多次匿名類舰罚,count就會(huì)進(jìn)行累加。
什么時(shí)候用匿名內(nèi)部類還是用實(shí)現(xiàn)類呢
- 使用匿名內(nèi)部類:需求不明確薛耻,可以考慮定義接口营罢,不管了直接讓調(diào)用過程中去確定即可或者只有一種情況
- 如果明確,建議一個(gè)接口饼齿,具體實(shí)現(xiàn)類饲漾,比如:支付:IPayService的 微信WexinPlayService AlipayService
問題
- 但是匿名內(nèi)部類還是不夠好,第一它往往很笨重缕溉,因?yàn)樗加煤芏嗫臻g考传。
- 怎么拯救呢?Lambda表達(dá)式
我們可以通過Java8里面提供的Lambda表達(dá)式進(jìn)行優(yōu)化和處理如下:
public class ApplePredicateTest {
public static List<Apple> filterApple(List<Apple> appleList, ApplePredicate predicate){
List<Apple> resultList = new ArrayList<>();
for (Apple apple : appleList) {
if (predicate.test(apple)) {
resultList.add(apple);
}
}
return resultList;
}
public static void main(String[] args) {
// 1证鸥、蘋果庫存
List<Apple> apples = new ArrayList<>();
apples.add(new Apple(1, "紅色", 200));
apples.add(new Apple(2, "綠色", 100));
apples.add(new Apple(3, "紅色", 134));
apples.add(new Apple(4, "淺紅色", 400));
apples.add(new Apple(5, "淺綠色", 220));
// 2僚楞、Lambda表達(dá)式過濾紅色蘋果
List<Apple> resultList1 = filterApple(apples, apple->apple.getColor().equals("紅色"));
System.out.println("==============紅色==================");
resultList1.forEach(System.out::println);
// 3勤晚、Lambda表達(dá)式過濾總量超過200g
List<Apple> resultList2 = filterApple(apples, apple-> apple.getWeight() > 200);
System.out.println("==============重量大于200g==================");
resultList2.forEach(System.out::println);
}
}
我們不得不承認(rèn)看上去比之前干凈多了,也很好看镜硕,因?yàn)榭雌饋砀駟栴}陳述本身运翼,也解決了我們啰嗦的問題。
多線程中的匿名內(nèi)部類處理方式
package java.lang;
/**
* The <code>Runnable</code> interface should be implemented by any
* class whose instances are intended to be executed by a thread. The
* class must define a method of no arguments called <code>run</code>.
* <p>
* This interface is designed to provide a common protocol for objects that
* wish to execute code while they are active. For example,
* <code>Runnable</code> is implemented by class <code>Thread</code>.
* Being active simply means that a thread has been started and has not
* yet been stopped.
* <p>
* In addition, <code>Runnable</code> provides the means for a class to be
* active while not subclassing <code>Thread</code>. A class that implements
* <code>Runnable</code> can run without subclassing <code>Thread</code>
* by instantiating a <code>Thread</code> instance and passing itself in
* as the target. In most cases, the <code>Runnable</code> interface should
* be used if you are only planning to override the <code>run()</code>
* method and no other <code>Thread</code> methods.
* This is important because classes should not be subclassed
* unless the programmer intends on modifying or enhancing the fundamental
* behavior of the class.
*
* @author Arthur van Hoff
* @see java.lang.Thread
* @see java.util.concurrent.Callable
* @since JDK1.0
*/
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
public class ApplePredicateTest03 {
public static void main(String[] args) {
Thread thread = new Thread(()->{
System.out.println("Hello Thread");
});
thread.start();
}
}
總結(jié)
- 行為參數(shù)化兴枯,就是一個(gè)方法接受多個(gè)不同行為的作為參數(shù),并在內(nèi)部使用它們矩欠。完成不能行為的能力财剖。
- 行為參數(shù)化可以讓代碼更好地使用不斷變化的要求,減輕未來的工作量癌淮。
- 傳遞代碼躺坟,就是講新行為作為參數(shù)傳遞給方法。但是在JDK8之前實(shí)現(xiàn)起來很啰嗦乳蓄,為接口申明許多只用一次的實(shí)現(xiàn)子類而造成啰嗦代碼咪橙。在JDK1.8之前可以使用匿名內(nèi)部類來減少。
- JavaApi包含很多可以用不同行為進(jìn)行參數(shù)的方法虚倒,包括:排序美侦,多線程和GUI處理等。