Java的函数式编程详解

 更新时间:2023年10月24日 08:20:46   作者:在下uptown  
用了这么久的Java8,我寻思这种话也好意思说出来吗,难道自己是PythonBoy出身就是看不懂Java的理由吗,身为一个合格的后端Boy不会还有人看不明白Java的函数式编程吧,接下来小编和大家浅聊一下Java的函数式编程,需要的朋友可以参考下

前言

虽然Jdk版本已经出到了20+,甚至IDEA创建maven默认项目Jdk版本都11了,但是你发任你发,我用Java8,最近别的组的同事要对接个需求,把代码仓库开给他之后反馈看不太明白代码。

用了这么久的Java8,我寻思这种话也好意思说出来吗,难道自己是PythonBoy出身就是看不懂Java的理由吗,身为一个合格的后端Boy不会还有人看不明白Java的函数式编程吧。

函数式编程

那什么是函数编程呢,说白了就是可以把函数作为参数传递给其他函数,亦或者将一个函数作为返回值从另一个函数中返回。

于是Jdk根据不同的场景提供了一些核心特性和函数式接口:

Consumer<T>:接受一个输入参数 T,并在方法内部执行操作,没有返回值。

Supplier<T>:不接受任何输入参数,提供一个结果 T。

Function<T, R>:接受一个输入参数 T,执行操作并返回一个结果 R。

Predicate<T>:接受一个输入参数 T,返回一个布尔值表示是否满足条件。

UnaryOperator<T>:接受一个输入参数 T,执行操作并返回一个与输入参数类型相同的结果。

BinaryOperator<T>:接受两个相同类型的输入参数 T,执行操作并返回一个相同类型的结果。

相信大家经常在业务代码中有过这样的场景,DAO层返回了一个Optional类,如果我们只想获得其中的某一个属性应该怎么写。

我们借助一个小菜鸡老弟的代码说,这段代码写的只能说一言难尽,按照他的想法,他只想拿到age字段,其实我们只需要借助map即可满足需求。

aa.map(Studnet::getAge)
.orElseThrow(
   () -> throw new Exception("user not found")
);

这里的orElseThrow其实就是传进去的一个方法,我们可以在方法里做些别的事,比如打印下信息之类的

aa.map(Student::getAge).orElseThrow(() -> {
    System.out.println("error! error!");
    return new Exception("user not found");
});

这就是一个很简单的函数式编程例子,把函数作为参数,在另一个函数中调用。这里举一个真实的业务案例,根据高内聚低耦合的抽象思想,我们保存数据的时候做一层前置数据校验,不同的类有不同的检查字段和方法,比如Student类要检查年龄是否大于18岁。

public class Java8Test {

    public static void main(String[] args) {
        Student student1 = Student.builder().age(10).name("uptown").build();
        savePeople(student1, (Student s1) -> {
            if (s1.getAge() < 18) {
                throw new RuntimeException("18岁禁!");
            }
        });
    }

    public static <T extends People> void savePeople(T t, Consumer<T> function) {
        function.accept(t);
        // 业务TODO
    }
}

@Data
@Builder
class People {

}

@Data
@Builder
class Student extends People {
    Integer age;
    String name;
}

这样写是不是比叠加if语句优化很多。

闭包

熟练使用函数式编程的jym对这个概念肯定不陌生,闭包就是能够读取其他函数内部变量的函数,借助网上js闭包的例子。

function makeFunc() {
	var name = "Mozilla";
	function displayName() {
		console.log(name);
	}
	return displayName;
}

var myFunc = makeFunc();
myFunc(); // "Mozilla"

可以通俗的想象成,你在房间里写了一段代码包含一个函数和一些变量。当你离开房间后,函数和变量仍然存在,它们就形成了一个闭包。当你再次进入房间时,你可以使用闭包中的函数来访问和修改之前已经修改过的变量,变量仍然记录着之前的状态。

那么Java中是否有闭包特性呢,答案是严格意义上说没有。

因为仔细想一下就发现在JVM里这套逻辑显然不符合,在栈中的变量函数结束后就会被清掉,怎么会记住之前的结果。但我们可以通过匿名内部类或lambad表达式实现,lambad本质上也是匿名内部类。

public static void main(String[] args) {
    final int i = 0;
    Supplier<Integer> sup = new Supplier<>(){
        Integer get(){
            return i;
        }
    };
}

为了保证正确性和一致性,JDK在语法上规定了lambad内部访问的局部变量必须是final修饰的。因为lambda表达式本质上创建了一个闭包,捕获了外部的局部变量,并在Lambda表达式的函数体中使用这些变量。

这只是其中一点,变量修饰为final还有一些数据一致方面的问题,这里就不再赘述了。

以上就是Java的函数式编程详解的详细内容,更多关于Java函数式编程的资料请关注脚本之家其它相关文章!

相关文章

  • spring 和 idea 建议不要使用 @Autowired注解的原因解析

    spring 和 idea 建议不要使用 @Autowired注解的原因解析

    @Autowired 是Spring框架的注解,而@Resource是JavaEE的注解,这篇文章主要介绍了spring和idea建议不要使用@Autowired注解的相关知识,需要的朋友可以参考下
    2023-11-11
  • 详解Java中用于查找对象哈希码值的hashCode()函数

    详解Java中用于查找对象哈希码值的hashCode()函数

    Java中入HashMap等一些键值对应的结构,基本上都可以用hashCode()来查找值,接下来我们就来详解Java中用于查找对象哈希码值的hashCode()函数:
    2016-05-05
  • Java中@ConditionalOnProperty注解使用

    Java中@ConditionalOnProperty注解使用

    在Spring Boot中,@ConditionalOnProperty注解是一种方便的工具,用于根据应用程序配置文件中的属性值来控制Bean的创建和加载,本文就来介绍一下Java中@ConditionalOnProperty注解使用,感兴趣的可以了解一下
    2023-11-11
  • Spring声明式事务@Transactional知识点分享

    Spring声明式事务@Transactional知识点分享

    在本篇文章里小编给大家整理了关于Spring声明式事务@Transactional详解内容,需要的朋友们可以参考下。
    2020-02-02
  • Java中finalize()详解及用法

    Java中finalize()详解及用法

    这篇文章主要介绍了Java中finalize()详解及用法的相关资料,final是Java的关键字,它所表示的是“这部分是无法修改的”,需要的朋友可以参考下
    2017-03-03
  • Java SpringBoot整合SpringCloud

    Java SpringBoot整合SpringCloud

    SpringCloud专注于为典型的用例和扩展机制提供良好的开箱即用体验,今天小编就带大家认识SpringCloud都有些什么特点,感兴趣的小伙伴留下来阅读全文吧
    2021-09-09
  • Spring Boot3 跨域配置 Cors的方式

    Spring Boot3 跨域配置 Cors的方式

    这篇文章主要介绍了Spring Boot3 跨域配置 Cors,通过使用CORS,开发人员可以控制哪些外部网页可以访问他们的资源,从而提高应用程序的安全性,本文结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2024-01-01
  • Java通过反射注解赋值的方法详解

    Java通过反射注解赋值的方法详解

    这篇文章主要为大家详细介绍了Java语言如何通过反射实现注解赋值,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以参考一下
    2022-07-07
  • Spring源码剖析之Spring处理循环依赖的问题

    Spring源码剖析之Spring处理循环依赖的问题

    大家都知道循环依赖依赖指的是Bean与Bean之间的依赖关系,循环依赖指的是两个或者多个Bean相互依赖,本文通过代码示例给大家讲解Spring处理循环依赖的问题,感兴趣的朋友一起看看吧
    2021-06-06
  • Logback 使用TurboFilter实现日志级别等内容的动态修改操作

    Logback 使用TurboFilter实现日志级别等内容的动态修改操作

    这篇文章主要介绍了Logback 使用TurboFilter实现日志级别等内容的动态修改操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08

最新评论