专业编程基础技术教程

网站首页 > 基础教程 正文

Java 17 Lambda 表达式和函数式接口

ccvgpt 2024-11-30 19:17:41 基础教程 1 ℃

Java 17 Lambda 表达式和函数式接口

在上一篇简单的说过 Lambda 的表达式基础用法, 这一章, 我们来聊聊 Lambda 表达式和函数式接口。

函数式接口的含义是只包含一个抽象方法的接口。 函数式接口可以包含多个默认方法、类方法、但是只能有一个声明的抽象方法。

Java 17 Lambda 表达式和函数式接口

函数式接口也就叫做: functional interface。

对于在实现中使用匿名内部类语法创建的接口实例,并且只需要实现一个抽象方法, 在这种情况下, 就可以使用 Lambda 表达式来创建对象。

从 Java 8 开始就提供了 @FunctionalInterface 注解来指明该接口为 Java 语法规范的函数式接口, 该注解通常放在接口定义的前面, 并且该注解是一种信息性批注类型,不会对功能而言不会有任何的作用。

定义来源:

具体的规范信息可以参考:https://docs.oracle.com/javase/specs/jls/se17/html/jls-9.html#jls-9.6.4.9 里面有详细的讲解。

举个例子:

@FunctionalInterface
public interface FiTest {
    void run();
}

对于下面的代码:

 public static void main(String[] args) {
     FiTest fiTest = () ->{
     System.out.println("Test run!");
     };
     fiTest.run();   
}

可以看到接口的实现调用。 这个和之前都使用方式都没有太大差别。 但是对于 FiTest 赋值给另外一个对象, 这我们赋值给 FiTest 接口的父类 Object。

Object object = () -> {
    System.out.println("Test and Object run!");
};

根据上面的例子可以看出来, 对于 Lambda 的函数式接口有两个限制。

  • Lambda 表达式的目标类型必须是明确的函数式接口
  • Lambda 表达式只能为函数式接口创建对象, Lambda 表达式只能实现一个方法, 因为它只能给只有一个抽象方法的接口(函数式接口)创建对象。

既然 Lambda 表达式需要目标类型是一个明确的函数式接口, 那就可以把上面的代码调整一下。

根据以上的代码, 我们可以总结一下, 对于 Lambda 表达式的常见方式。

  • 可以将 Lambda 表达式赋值给接口式类型的变量。
  • 可以将 Lambda 表达式作为函数式接口类型的参数传给某个方法
  • 可以是函数式接口对 Lambda 表达式进行强转。

在 Java 8 开始就定义了 java.util.function 包。 预定义了一系列的函数式接口, 在 Java 17 中该包在如下位置:

在模块 java.base 的 java.util.function 包中。

定义的内容大概如下:

参考地址为:https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/function/package-summary.html

此包中的函数接口遵循可扩展的命名约定。 并且包含几个基本的函数类型。

  • xxxFunction
  • xxxConsumer
  • xxxPredicate
  • xxxSupplier

写个小例子:

这样的话, 可以针对已有的函数接口灵活使用。这个函数接口, 其中的泛型<Integer> 是函数结果的类型。 该函数式接口的意义是接受一个 int 值参数, 并生成结果的函数。其接口函数方法是 R apply(int value);

这里还有另外的用法, 可以传入两个泛型参数, 第一个参数是输入的类型。 第二个参数是结果的类型。 同样也是接受一个参数, 生成结果的函数。 同样的函数方法是 apply(Object);

函数式接口知识点, 暂告一段落吧。

每篇一句:

IT 领域只是更新换代之快需要我们不断的往前奔跑, 当我们痛苦地追逐时尚的新鲜玩意时,更需要放慢脚步,冷静的修炼自己的“内功”,这样才能以不变应万变,立于不败之地。

最近发表
标签列表