技术中心

这里象征着我们的态度和能力

>Java8和Scala中的高阶函数
作者:中国IT实验室    来源:中国IT实验室    发布时间:2012-09-03      浏览次数:7915
分享到:
欢迎进入Java社区论坛,与200万技术人员互动交流 >>进入

    函数文本最大的优势就是可以像字符串或者对象等其他文本(literal)一样传送它。这种特性为构建高度紧凑和可重用代码提供无限的可能性。

    1、我们的第一个高阶函数

    当我们将一个函数文本传送给一个方法的时候,我们最主要的是一个接收方法参数的方法(这个确实很绕-_-|||),这类方法就叫做高阶函数。上文Swing例子中提到的 addActionListener 方法恰好属于这类。我们还可以定义自己的高阶函数来为自己提供许多便利。让我们看一个简单的例子:

  1. def measure[T](func:=>T):T {  
  2.     val start = System.nanoTime()  
  3.     val result = func  
  4.     val elapsed = System.nanoTime() - start;  
  5.     print("The execution of this call took: %s ns".format(elapsed));  
  6.     result  

    在这个例子中,我们声明了一个名为measure的方法用来计算这个名为func的函数文本的回调所需要的时间。func 方法的签名(signature)是它不接收任何参数并且返回一个泛型类型T.正如你所看到的,Scala中的函数并不一定需要参数尽管它们能够――而且往往也含有参数。

    现在我们可以向 measure 方法中传递任何函数文本(或者方法)。

  1. def myCallback = {  
  2.     Thread.sleep(1000)  
  3.     "I just took a poewrnap" 
  4. }   
  5. val result = measure(myCallback);   
  6. > The execution of this call took: 100244900 ns 

    从概念的角度讲我们所做的,就是将计算方法调用时间和实际的运算区分开来。我们构造了两块可以重用、松散耦合、类似于拦截器(interceptor)的代码块(measure和myCallback)

    2、通过高阶函数实现重用

    先看一个假设的例子,两个可重用构造略紧耦合:

  1. def doWithContact(fileName:String, handle:Contact => Unit):Unit = {  
  2.     try {  
  3.         val contactStr = io.Source.fromFile(fileName).mkString  
  4.         val contact = AContactParser.parse(contactStr)  
  5.         handle(contact)  
  6.     }  
  7.     catch {  
  8.         case e: IOException => println("couldnt load contact file: " + e);  
  9.         case e: ParseException => println("coulndt parse contact file: " + e);  
  10.     }  

    doWithContact 方法从文件中读取电子名片之类的联系方式然后将数据提供给一个解析器(parser)将数据转化成为联系领域的对象。然后这个对象被传递给一个函数文本回调 handle. doWithContact 方法 很函数文本均返回 Unit 类型,等同于java中的返回void的方法。

    现在,我们可以定义各种各样的可以传递给 doWithContact 的回调函数:

  1. val storeCallback = (c:Contact) => ContactDao.save(c)  
  2. val sendCallback = (c:Contact) => {  
  3.     val msgBody = AConverter.convert(c)  
  4.     RestService.send(msgBody)  
  5. }  
  6. val combineCallback = (c:Contact) => {  
  7.     storeCallback(c)  
  8.     sendCallback(c)  
  9. }  
  10. doWithContact("custerX.vcf", storeCallback)  
  11. doWithContact("custerY.vcf", sendCallback)  
  12. doWithContact("custerZ.vcf", combineCallback)  
  13. doWithContact("custerZ.vcf", combineCallback) 

    回调函数也可以通过内联传递:

  1. doWithContact("custerW.vcf", (c:Contact) => ContactDao.save(c)) 

    3、Java 8 中的高阶函数

    java 8 中的等效实现看起来十分相似――使用目前的语法建议:

  1. public interface Block<T> {  
  2.     void apply(T t);  
  3. }  
  4. public void doWithContact(String fileName, Block<Contact> block) {  
  5.     try {  
  6.         String contacStr = FileUtils.readFileToString(new File(fileName));  
  7.         Contact.apply(contact);  
  8.         block.apply(contact);  
  9.     }  
  10.     catch (IOException e) {  
  11.         System.out.println("cloudnt load contact file: " + e.getMessage());  
  12.     }     
  13.     catch (ParseException e) {  
  14.         System.out.println("cloudnt parse contact file: " + e.getMessage());  
  15.     }  
  16. }  
  17. //usage  
  18. doWithContact("custerX.vcf", c -> ContactDao.save(c)) 

    4、使用高阶函数的益处

    正如你见到的,函数帮助我们干净地将对象的创建和处理区分开来。通过这种方法,新的业务逻辑处理对象就可以轻易的添加进来而没有必要同对象创建逻辑相耦合。

    结果就是,我们通过使用高阶函数来使我们的代码保持DRY(Dontt Repeat Yourself) 因而,程序员可以从一个非常细粒度的代码重用中获得最佳利益。

4000-880-989
(24小时热线)
联系客服
微信公众号

官方公众号

小程序

©2008-2022 CORPORATION ALL Rights Reserved. 昆明奥远科技有限公司版权所有 滇ICP备09003328号-1 滇公网安备 53011102000818号 增值电信业务经营许可证号:滇B2-20110045
昆明那家网络公司好,新媒体运营,网站优化,网络推广,网站建设,网页设计,网站设计,网站推广,云南网站公司,昆明新媒体公司,云南网红主播,昆明SEO公司,昆明网站建设,昆明网络推广,昆明网站优化,昆明网站推广,红河网站建设,大理网络公司,曲靖网络公司,丽江网站设计,昭通网络公司,保山大数据服务,智慧高速建设,智慧校园服务,云南IDC服务商,网络安全测评,等保测评,网站关键词排名优化服务,服务客户尽超2000余家,一切尽在奥远科技,服务电话:13888956730