java 为什么要实现 function?

1、使Function获取序列化能力;

3、建一些业务代码进行测试;

// 从序列化方法取出序列化的lambda信息

// 从field取出字段名,可以根据实际情况调整

建一些业务代码进行测试

* 字段名注解。测试用

* 用户实体类。测试用

我们知道,Java 是面向对象的编程语言,我们对抽象的概念肯定不陌生,面向对象编程就是对数据进行抽象。Java 8 之后出现了 lambda 表达式,让我们可以用 Java 实现函数式编程,即对行为抽象。

首先我们来简单了解一下 Java 的 lambda 表达式的用法,看下面的代码:

// 4. 有两个参数,有返回值,将方法体的计算结果作为返回值返回 // 5. 注明类型的参数

仅当接口只有一个抽象方法时,才可以使用 lambda 表达式。我们知道,Runnable接口只有一个run()方法,所以我们可以用 lambda 表达式作为行为传递给Runnable接口,告诉它你的run()方法将使用我传递的行为,并将生成的对象实例赋值给noArgsNoRet

其他的几条语句也是一样的概念,我们可以先不用管他们都是什么接口,接下来看一下 lambda 表达式本身。每一个 lambda 表达式都会使用一个->符号,作为分隔符,左边代表方法的参数,右边代表方法体。只有一个参数可以省略括号();只有一条语句的方法体可以省略花括号{}。所以:

  1. 无参数和多个参数必须用括号
  2. 参数注明类型必须用括号

所以怎么理解 Java 的函数式编程?我们先来参考一下 js 语言,在 js 的函数式编程中,有一个特点,即:函数是一等公民。意思是,函数跟其它数据类型一样处于平等地位,可以赋值给其他变量,也可以作为参数传入另一个函数。

Java 的概念略有不同,但是可以有助于我们理解。

那么,Java 将函数赋值给变量了吗?

光看上面的例子代码,好像是这样的噢,一个=号,像是将右边的函数赋值给了左边的变量。

但是!不要忘了,Java 是面向对象的语言,变量只会被赋值为对象或基本类型,很显然函数不可能被赋值给变量!

所以说,Java只是将函数这个行为,传递给了抽象接口的方法,告诉这个抽象接口,你的方法要用我的这个函数实现!

这就是所谓的对行为抽象。

理解了 Java 如何对行为进行抽象,并使用 lambda 表达式实现,我们就可以来看一下 java.util.function包了。我发现网上绝大部分对这个包的讲解都很少,为什么要有这个包?里面的接口是干什么用的?

在这个包里面,全部都是函数式接口,都使用了@FunctionalInterface注解进行声明。我们直接来看一下里面的接口,找名字就叫函数的Function接口,它的关键的代码如下:

@FunctionalInterface注解声明这个包是函数式接口,编译的时候会判断接口里面是不是只有一个抽象方法,如果不是会报错。

接口声明了两个泛型,分别用在抽象方法R apply(T t)上。表示接受一个类型的参数,返回一个类型的返回值。普通的使用方法很简单:

// 1. 声明函数对象实例 // 接收一个Integer类型的参数,返回String类型的返回值 // 2. 使用传递给函数的方法体

相当于给你提供了一个开箱即用的函数式接口,但是这么使用体现不了函数式接口的优势,我们要对行为抽象,看下面这个例子:

// 将行为进行抽象,在你需要操作的时候再定义

这个例子没有实际意义,但是表达了对行为进行抽象的特征,将Function函数接口作为参数,调用方法时再对行为进行具体定义,也可以理解为对代码进行传递。

在最有用的操作容器的Stream类,你会看到非常多的这种对行为进行抽象。因篇幅原因,Stream将会在下一篇文章进行讲解。

java.util.function包的接口非常多,有40多个,每一个接口声明了不同的参数和返回值,我们怎么记得住这么多?

其实他们是有规律的,根据名称来进行分类,有如下几个大类:

  1. Consumer(消费):接受参数,无返回值
  2. Function(函数):接受参数,有返回值
  3. Operator(操作):接受参数,返回与参数同类型的值
  4. Supplier(供应):无参数,有返回值

比如说Consumer接口和BiConsumer接口,他们分别接受一个参数和两个参数,但共同点是都没有返回值,都是消费者。其他同理,完整的接口列表如下:

接受一个参数,无返回值
接受两个参数,无返回值
接受一个double类型的参数,无返回值
接受一个int类型的参数,无返回值
接受一个long类型的参数,无返回值
接受一个自定义类型的参数和一个double类型的参数,无返回值
接受一个自定义类型的参数和一个int类型的参数,无返回值
接受一个自定义类型的参数和一个long类型的参数,无返回值
接受一个参数,有返回值
接受两个参数,有返回值
接受一个double类型的参数,有返回值
接受一个int类型的参数,有返回值
接受一个long类型的参数,有返回值
接受一个int类型的参数,返回一个double类型的值
接受一个int类型的参数,返回一个long类型的值
接受一个long类型的参数,返回一个double类型的值
接受一个long类型的参数,返回一个int类型的值
接受一个double类型的参数,返回一个int类型的值
接受一个double类型的参数,返回一个long类型的值
接受两个参数,返回一个double类型的值
接受一个参数,返回一个double类型的值
接受两个参数,返回一个int类型的值
接受一个参数,返回一个int类型的值
接受两个参数,返回一个long类型的值
接受一个参数,返回一个long类型的值
接受两个相同类型的参数,返回一个相同类型的值
接受两个double类型的参数,返回一个double类型的值
接受一个double类型的参数,返回一个double类型的值
接受两个int类型的参数,返回一个int类型的值
接受一个int类型的参数,返回一个int类型的值
接受两个long类型的参数,返回一个long类型的值
接受一个long类型的参数,返回一个long类型的值
接受一个参数,返回一个相同类型的值
接受一个参数,返回一个boolean类型的值
接受两个参数,返回一个boolean类型的值
接受一个double类型的参数,返回一个boolean类型的值
接受一个int类型的参数,返回一个boolean类型的值
接受一个long类型的参数,返回一个boolean类型的值
无参数,返回一个boolean类型的值
无参数,返回一个double类型的值
无参数,返回一个int类型的值
无参数,返回一个long类型的值

了解了这些,我们基本就掌握了 Java 函数式编程的基础了,在这些基础上,咱们平常就可以方便地编写函数式接口的实现代码了。

当然,函数式接口的最佳实践:Stream类,我们还没有介绍到,可以关注我或者公众号:Java老狗。我们下一期将会更新Stream类的内容,它是对集合操作功能的增强,专注于对集合的各种高效、便利、优雅的聚合操作,显著的提高编程效率和可读性。且 Stream 提供了并行计算模式,可以简洁的编写出并行代码,能充分发挥如今计算机的多核处理优势。

我要回帖

更多关于 javafunction场景 的文章

 

随机推荐