JDK1.8特性之函数式接口
我们都知道,从JDK1.8开始,java已经对函数式编程有了比较完善的支持,除了我们常用的stream之外,还有Optional、Supplier、Function等,其中Function就是函数式接口的一种方式,函数式编程极大提升了我们的编程效率和代码逻辑简洁度,今天我们就抽点时间来看下@FunctionalInterface(函数式接口)的简单应用。
@FunctionalInterface虽然@FunctionalInterface和其他的lambda一样,都是jdk1.8引入的,但相比于stream和Optional这两种常用的新特性,我对@FunctionalInterface的了解就显得很浅薄了。
哪怕是经常在stram()中用到它,但对于具体如何使用它,如何更好地应用它,我还真的是一知半解。
下面我们先通过一个简单的实例,来见识下@FunctionalInterface的魅力:
一个简单场景假设我们有一个方法,需要在方法中的某个执行结果为success的时候执行一段代码或者调另一个方法,在执行结果为failed的时候执行另一段代码,在传统实现下,我们需要这样操作:
publicvoiddealThing(Stringparameter){//执行业务Stringresult="123".equals(parameter)?"success":"failed";if("success".equals(parameter)){System.out.println("业务1执行成功");}if("failed".equals(parameter)){System.out.println("业务1执行失败");}}
当然这样写没有任何问题,但是如果我们执行结果的逻辑还需要在其他方法中执行,而且其中成功和失败的业务处理还不尽相同,这样在传统操作中,我们要么需要多加一层业务判断,要么重新写个方法,不过这两种方式都增加了冗余代码:
//增加逻辑处理publicvoiddealThing(Stringparameter){if("业务1".equals(parameter)){//执行业务Stringresult="123".equals(parameter)?"success":"failed";if("success".equals(result)){System.out.println("业务1执行成功");}if("failed".equals(result)){System.out.println("业务1执行失败");}}else{//执行业务Stringresult="124".equals(parameter)?"success":"failed";if("success".equals(result)){System.out.println("业务2执行成功");}if("failed".equals(result)){System.out.println("业务2执行失败");}}}//或者重写方法publicvoiddealThing2(Stringparameter){//执行业务Stringresult="124".equals(parameter)?"success":"failed";if("success".equals(parameter)){System.out.println("业务2执行成功");}if("failed".equals(parameter)){System.out.println("业务2执行失败");}}
当然,如果是一两个业务,我觉得都还可以接受,但如果是十几个或者几十个业务的时候,这种处理方式就显得很不友好,而且往往success和failed需要处理的业务逻辑可能不尽相同,所以我们还需要更友好更能够简化我们业务实现逻辑的方法,这时候就到了函数式接口发光发热的时候了:
函数式接口应用如果采用函数式接口的方式,对于上面这样的需求场景,我们只需要增加两个Consumer入参即可——成功回调、失败回调:
/***结果回调*@paramresult*@paramsuccessFun*@paramfailedFun*/publicvoiddealThing(Stringparameter,ConsumersuccessFun,Consumer failedFun){//执行业务Stringresult="124".equals(parameter)?"success":"failed";if("success".equals(result)){successFun.accept(result);}if("failed".equals(result)){failedFun.accept(result);}}
这里的Consumer就是函数式接口的一种,使用也很简单,就是在调用具体方法的时候,要提供接口的具体实现,也就是我们上面的successFun、failedFun入参,具体调用实例如下:
Stringparameter="123";newFunctionalInterfaceTest().dealThing(parameter,s->{System.out.println("业务执行成功"+s);},f->{System.out.println("业务执行失败"+f);});
运行结果如下:
Consumer函数式接口下面我们来简单看下Consumer接口的基本结构:
和我们通常定义的接口有所不同的是,函数式接口有一个@FunctionalInterface注解,其中的accept方法就是我们在调用方法时需要实现的方法。除了Consumer函数式接口之外,java还为我们提供了其他很多有用的函数式接口,比如Function,与Consumer不同的是,Function提供的函数式接口是可以有返回值的:
定义自己的函数式接口关于官方提供的函数式接口我们就先看这么多,下面我们一起来看下如何定制自己的函数式接口,其实也很简单:
首先是定义接口和接口方法,然后加上@FunctionalInterface,这样一个函数式接口就定义好了:
@FunctionalInterfacepublicinterfaceMyFunctionInterface{voidsyske(Tt);}
使用和我们上面演示的用法没有任何区别:
newFunctionalInterfaceTest().functionTest("syske","hello",parameter->System.out.println("syske,"+parameter));
当然除了上面我们演示的这种方式之外,我们还可以通过下面这种方式来使用函数式接口:
publicvoidsyskeFun(Stringparameter){System.out.println("syske,"+parameter);}//当前类的非静态方法调用newFunctionalInterfaceTest().functionTest("syske","hello",this::syskeFun);//静态方法调用,在这种情况下,需要把syskeFun定义为静态方法newFunctionalInterfaceTest().functionTest("syske","hello",FunctionalInterfaceTest::syskeFun);
需要注意的是,函数式接口中只能定义一个未实现的接口,否则会报编译错误:
多参数函数式接口上面我们演示的都是单参数的函数式接口,其实官方也提供了很多其他的函数式接口,比如带返回值的函数式接口Function、多参数的接口BiFunction
这里的BiFunction有两个入参和一个返回值,如果两个参数依然满足不了你的需要,你还可以自己定义多参数接口,这里我定义的函数式接口有5个参数:
@FunctionalInterfacepublicinterfaceMyFunctionInterface2{voidsyske(Tt,Rr,Uu,Xx,Yy);}
调用方式也是大同小异:
publicvoidsetMyFunctionInterface2(Stringt,Stringr,Stringu,Stringx,Stringy,MyFunctionInterface2结语interface2){interface2.syske(t,r,u,x,y);}newFunctionalInterfaceTest().setMyFunctionInterface2("parameter1","parameter2","parameter3","parameter4","parameter5",(t,r,u,x,y)->System.out.printf("%s.%s.%s.%s.%s",t,r,u,x,y));
相比于传统的方法调用,函数式接口的入参更灵活也更方便,让我们可以在不同的业务中使用不同的逻辑实现方式,可以极大简化代码中的if-else逻辑,甚至在某些场景下,还可以代替策略模式。好了,关于函数式接口的简单介绍和应用我们就先分享这么多,感兴趣的小伙伴可以亲自动手试试,当然最好的实践就是在实际应用开发中使用它,并让它为我们的开发工作带来便利。
- END -相关阅读
-
世界热推荐:今晚7:00直播丨下一个突破...
今晚19:00,Cocos视频号直播马上点击【预约】啦↓↓↓在运营了三年... -
NFT周刊|Magic Eden宣布支持Polygon网...
Block-986在NFT这样的市场,每周都会有相当多项目起起伏伏。在过去... -
环球今亮点!头条观察 | DeFi的兴衰与...
在比特币得到机构关注之后,许多财务专家预测世界将因为加密货币的... -
重新审视合作,体育Crypto的可靠关系才能双赢
Block-987即使在体育Crypto领域,人们的目光仍然集中在FTX上。随着... -
简讯:前端单元测试,更进一步
前端测试@2022如果从2014年Jest的第一个版本发布开始计算,前端开发... -
焦点热讯:刘强东这波操作秀
近日,刘强东发布京东全员信,信中提到:自2023年1月1日起,逐步为...