您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > JAVA

浅析Java中函数式编程、匿名函数和泛型

时间:2023-09-10 12:03:44  来源:  作者:Java学研大本营

使用函数式编程可以减少代码重复,使代码更易于理解。

JAVA编程语言以其面向对象的特性而闻名,但也因其冗长和繁琐的异常处理机制而而广受批评。当Java语言在1.8版本引入函数式编程能力时,人们并没有马上理解到这如何给程序员提供帮助。

图片

本文给大家讲解一个示例,以说明函数式编程如何提高代码的重用性和可读性。

1 问题

为了实现功能,第三方编写的通信客户端使用了依赖注入和注释。然而,该客户端存在一些问题,例如抛出已检查异常、缺乏日志记录和重试能力。因此,我们需要对该客户端的功能进行封装,以添加重试功能、日志记录和良好的异常处理。

如果没有函数式编程,那么程序需要创建一个外观,将每个客户端功能都包装在委托中,并添加日志记录、异常处理和通信重试的逻辑。客户端共有50个需要封装的函数,这将导致几乎完全相同的50个副本的代码,仅有调用的客户端函数和传递的数据类型有所不同。这样会带来大量的重复代码问题。

为了解决这个问题,要使用函数式编程的方式对该客户端功能进行封装,以实现重试能力、日志记录和良好的异常处理。

2 使用函数式编程解决问题

解决方案是添加1或2个专门用于处理异常、执行日志记录和实现重试循环的方法。但是,它们需要调用通信客户端中的特定函数。

使用函数式编程,方法可以将函数作为其参数接收。该方法不需要在设计时知道哪个函数。Java(因为这与其他编程语言不同)所要求的是函数具有预期的签名。

在我们的情况下,我们需要2种变体:BiFunction签名和BiConsumer签名。区别在于BiFunction返回一个值,而BiConsumer则不返回。

2.1 示例代码:委托

public final ActionResult<List<Order>>
    downloadOrders() {
    return get(
      ".downloadOrders()",
      (
        client,
        apiKey
      ) -> client.downloadOrders(apiKey.toString())
    );
  }

上面的示例没有显示错误处理、日志记录和重试循环。这是由get(String, BiFunction)方法执行的。因此,我们不需要50个重复的错误处理、日志记录和重试循环,而是有50个易于理解的委托。

get(String, BiFunction)方法回调传入的BiFunction,我们在上面看到了这一点:

(    
  client,
  apiKey
) -> client.downloadOrders(apiKey.toString())

我们可能会从JavaScript中认识到这一点。语法是一个BiFunction的lambda表示法:它接受2个参数,可能做一些事情,并返回一些东西。它是一个回调函数,根据需要即时创建,并且因为它没有名称,所以它保持匿名(并由编译器分配标识)。它的参数client和apiKey在方法get(String, BiFunction)内生成,并在运行时传回回调函数中。它看起来像这样:

2.2 示例代码:接受函数作为参数的包装器

private final <T>
    ActionResult<T>
    get(
      final String caller,
      final BiFunction<
        Client,
        ApiKey,
        T
      > callback
    ) {
    final Client client = Client.newInstance(caller);
    final ApiKey key = this.getKey();
    final MutableList<Exception> errors = Lists.mutable.empty();
    boolean mustRetry = true;
    for (
      int retryCount = 0;
      mustRetry && retryCount < MAX_RETRIES;
      retryCount += 1
    ) {
      try {
        return new ActionResult<T>(
          callback.Apply(
            client,
            apiKey
          )
        ).with(errors);
      } catch (Exception ex) {
        mustRetry = mustRetry(ex);
        if (mustRetry) {
          try {
            TimeUnit.SECONDS.wAIt(1 << (retryCount + 1));
          } catch (InterruptedException ie) {
            errors.add(ie);
          }
        } else {
          errors.add(ex);
        }
      }
    }
    return ActionResult.<T>empty()
      .with(errors);
  }

在那段代码中,BiFunction通过声明进行回调:

callback.apply(
  client,
  apiKey
)

请注意,get(String, BiFunction)不知道回调返回的数据类型。在像Java这样的强类型和显式类型编程语言中,通常不可能。直到泛型引入Java编程语言之前,这是不可能的。这就是为什么代码中存在:它是回调返回的数据类型的占位符。

请注意,调用站点也没有指定返回值的数据类型。相反,它由客户端函数的返回值和委托上指定的返回数据类型隐含。如果它们不匹配,编译器将发出警告,保持数据类型良好且检查过。

3 总结

  • 坏的抽象是面向对象编程中许多问题的根源。我们希望将目前的两个异常处理和重试循环包装器减少到一个包装器,但是由于一个接受BiFunction回调,另一个接受BiConsumer回调,还没有找到合适的方法。因为从概念上讲,它们执行不同的操作:发送和接收。使用相同的包装器可能会破坏这种概念上的区别。总之,对于现在来说值得高兴的是避免了重复使用50个包装器的情况。

  • 当然,有些优秀的编译器可能会检测到代码重复,并采取一些技巧将它们减少为具有不同回调的单个包装器。然而,这并非我们当前关注的重点。我们的目标是消除重复代码并提高代码的可读性。

  • 从理论上讲,使用这个包装器和函数委托可能会导致程序变慢。然而,根据经验,由于与远程通信伙伴进行通信时遇到的网络延迟,潜在的几毫秒延迟相对微不足道。尽管如此,如果在您的环境中这导致了明显的性能下降,请测量吞吐量并进行相应的调整。

  • 静态代码分析工具若能提供有关消除重复代码的建议,将对代码优化非常有益。这样的工具可以帮助开发人员识别和消除重复的代码段,从而提高代码的可读性、可维护性和性能。



Tags:函数式编程   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
浅析Java中函数式编程、匿名函数和泛型
使用函数式编程可以减少代码重复,使代码更易于理解。Java编程语言以其面向对象的特性而闻名,但也因其冗长和繁琐的异常处理机制而而广受批评。当Java语言在1.8版本引入函数式...【详细内容】
2023-09-10  Search: 函数式编程  点击:(216)  评论:(0)  加入收藏
三分钟读懂Java函数式编程(FP)的意义所在
概述背景函数式编程的理论基础是阿隆佐&middot;丘奇(Alonzo Church)于1930 年代提出的 &lambda; 演算(Lambda Calculus)。&lambda; 演算是一种形式系统,用于研究函数定义、函数应...【详细内容】
2023-04-06  Search: 函数式编程  点击:(278)  评论:(0)  加入收藏
JS函数式编程和递归探索:路由树的操作
开始切入正题之前,有必要告知大家一下,这篇文章可能有一些深度,初学者可能理解会有些吃力。我会尽量把复杂问题简单化,争取让每个阅读的童鞋们都能看得懂。希望你对element-ui,vu...【详细内容】
2022-03-16  Search: 函数式编程  点击:(334)  评论:(0)  加入收藏
沉迷面向对象编程不可自拔?函数式编程了解一下
函数式编程已经存在了60多年,但是到目前为止,它一直都很小众。只有像Google这样的改变游戏规则的企业才会依赖函数式编程,普通程序员对此几乎一无所知。 这种情况很快就要被改...【详细内容】
2020-11-05  Search: 函数式编程  点击:(208)  评论:(0)  加入收藏
JavaScript中的函数式编程
JavaScript是一种发展迅速的语言。这篇文章,我想展示一些有关如何在JavaScript中应用函数式编程的示例。JavaScript中的函数式编程即使函数式编程可以极大地改善应用程序的代...【详细内容】
2020-06-09  Search: 函数式编程  点击:(270)  评论:(0)  加入收藏
Python4大函数式编程函数,每一个都是经典!
函数式编程或者函数程序设计,又称泛函数编程,是一种编程范式。在Python中,函数编程主要有以下4个函数的使用构成:lambda()、map()、reduce()、filter(),下面我们来一一讲解这些...【详细内容】
2020-04-16  Search: 函数式编程  点击:(324)  评论:(0)  加入收藏
函数式编程,真香
为什么函数式编程正在上升 编程范例是一个术语,用于描述编写命令的方法。 语言的真正思想是建立在其编程范例之上的。 最著名的三种范例是面向对象的程序设计,命令式程序设计...【详细内容】
2020-03-11  Search: 函数式编程  点击:(630)  评论:(0)  加入收藏
一文带你了解 JavaScript 函数式编程
函数式编程在前端已经成为了一个非常热门的话题。在最近几年里,我们看到非常多的应用程序代码库里大量使用着函数式编程思想。...【详细内容】
2019-09-24  Search: 函数式编程  点击:(737)  评论:(0)  加入收藏
Python函数式编程,Python闭包
前置内容为了更容易理解闭包,在说闭包之前,讲一下两个概念:作用域和嵌套函数。 作用域作用域是变量能被访问的范围,定义在函数内的变量是局部变量,局部变量的作用范围只能在函数...【详细内容】
2019-07-17  Search: 函数式编程  点击:(1102)  评论:(0)  加入收藏
▌简易百科推荐
Java 8 内存管理原理解析及内存故障排查实践
本文介绍Java8虚拟机的内存区域划分、内存垃圾回收工作原理解析、虚拟机内存分配配置,以及各垃圾收集器优缺点及场景应用、实践内存故障场景排查诊断,方便读者面临内存故障时...【详细内容】
2024-03-20  vivo互联网技术    Tags:Java 8   点击:(14)  评论:(0)  加入收藏
如何编写高性能的Java代码
作者 | 波哥审校 | 重楼在当今软件开发领域,编写高性能的Java代码是至关重要的。Java作为一种流行的编程语言,拥有强大的生态系统和丰富的工具链,但是要写出性能优异的Java代码...【详细内容】
2024-03-20    51CTO  Tags:Java代码   点击:(21)  评论:(0)  加入收藏
在Java应用程序中释放峰值性能:配置文件引导优化(PGO)概述
译者 | 李睿审校 | 重楼在Java开发领域,优化应用程序的性能是开发人员的持续追求。配置文件引导优化(Profile-Guided Optimization,PGO)是一种功能强大的技术,能够显著地提高Ja...【详细内容】
2024-03-18    51CTO  Tags:Java   点击:(24)  评论:(0)  加入收藏
Java生产环境下性能监控与调优详解
堆是 JVM 内存中最大的一块内存空间,该内存被所有线程共享,几乎所有对象和数组都被分配到了堆内存中。堆被划分为新生代和老年代,新生代又被进一步划分为 Eden 和 Survivor 区,...【详细内容】
2024-02-04  大雷家吃饭    Tags:Java   点击:(56)  评论:(0)  加入收藏
在项目中如何避免和解决Java内存泄漏问题
在Java中,内存泄漏通常指的是程序中存在一些不再使用的对象或数据结构仍然保持对内存的引用,从而导致这些对象无法被垃圾回收器回收,最终导致内存占用不断增加,进而影响程序的性...【详细内容】
2024-02-01  编程技术汇  今日头条  Tags:Java   点击:(68)  评论:(0)  加入收藏
Java中的缓存技术及其使用场景
Java中的缓存技术是一种优化手段,用于提高应用程序的性能和响应速度。缓存技术通过将计算结果或者经常访问的数据存储在快速访问的存储介质中,以便下次需要时可以更快地获取。...【详细内容】
2024-01-30  编程技术汇    Tags:Java   点击:(72)  评论:(0)  加入收藏
JDK17 与 JDK11 特性差异浅谈
从 JDK11 到 JDK17 ,Java 的发展经历了一系列重要的里程碑。其中最重要的是 JDK17 的发布,这是一个长期支持(LTS)版本,它将获得长期的更新和支持,有助于保持程序的稳定性和可靠性...【详细内容】
2024-01-26  政采云技术  51CTO  Tags:JDK17   点击:(88)  评论:(0)  加入收藏
Java并发编程高阶技术
随着计算机硬件的发展,多核处理器的普及和内存容量的增加,利用多线程实现异步并发成为提升程序性能的重要途径。在Java中,多线程的使用能够更好地发挥硬件资源,提高程序的响应...【详细内容】
2024-01-19  大雷家吃饭    Tags:Java   点击:(105)  评论:(0)  加入收藏
这篇文章彻底让你了解Java与RPA
前段时间更新系统的时候,发现多了一个名为Power Automate的应用,打开了解后发现是一个自动化应用,根据其描述,可以自动执行所有日常任务,说的还是比较夸张,简单用了下,对于office、...【详细内容】
2024-01-17  Java技术指北  微信公众号  Tags:Java   点击:(95)  评论:(0)  加入收藏
Java 在 2023 年仍然流行的 25 个原因
译者 | 刘汪洋审校 | 重楼学习 Java 的过程中,我意识到在 90 年代末 OOP 正值鼎盛时期,Java 作为能够真正实现这些概念的语言显得尤为突出(尽管我此前学过 C++,但相比 Java 影响...【详细内容】
2024-01-10  刘汪洋  51CTO  Tags:Java   点击:(74)  评论:(0)  加入收藏
站内最新
站内热门
站内头条