程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Java8新特性

    • Java8新特性简介
    • Lambda 表达式
    • 函数式接口
    • 方法的引用
      • 1. 方法引用概述
      • 2. 使用场景
      • 3. 方法引用的使用格式
      • 4. 方法引用的使用要求
      • 5. 方法引用的使用示例
        • 1. 对象::实例方法
        • 2. 类::静态方法
        • 3. 类::实例方法
      • 6. 方法引用的总结和建议
    • 构造器和数组的引用
    • Stream 流式编程
    • 并行流与串行流
    • Optional 类的使用
    • 对反射的支持增强
    • 接口中的默认方法与静态方法
    • 新时间日期API
    • Try-with-Resources 升级
    • 重复注解与类型注解
  • Java9新特性

  • Java10新特性

  • Java11新特性

  • Java12新特性

  • Java13新特性

  • Java14新特性

  • Java15新特性

  • Java新特性
  • Java8新特性
scholar
2024-08-24
目录

方法的引用

# 方法引用

  • 1. 方法引用概述
  • 2. 使用场景
  • 3. 方法引用的使用格式
  • 4. 方法引用的使用要求
  • 5. 方法引用的使用示例
    • 1. 对象::实例方法
    • 2. 类::静态方法
    • 3. 类::实例方法
  • 6. 方法引用的总结和建议

# 1. 方法引用概述

方法引用是 Lambda 表达式的简化形式,通过方法的名字直接指向现有方法。方法引用使代码更加简洁、直观,并且可以避免重复编写已有的逻辑。可以看作是对 Lambda 表达式的进一步优化,当 Lambda 体中的内容是对现有方法的直接调用时,方法引用是一种更优雅的方式。

  • 方法引用的本质:方法引用和 Lambda 表达式一样,都是通过实现一个函数式接口的抽象方法来完成任务。函数式接口只有一个抽象方法,这使得方法引用可以匹配并替代 Lambda 表达式的实现。
  • 方法引用需要一个接口对象接收:因为方法引用本质上是在实现函数式接口的抽象方法,所以它需要一个函数式接口对象接收,就像 Lambda 表达式一样。这个函数式接口的抽象方法决定了方法引用所指向方法的参数和返回值。
  • 参数和返回值的匹配:在方法引用中,被引用的方法的参数和返回值必须与函数式接口的抽象方法一致。正因为这一点,方法引用可以作为 Lambda 表达式的替代,并且让代码更加简洁。

# 2. 使用场景

当 Lambda 表达式中的操作已经有现成的方法可以直接使用,并且该方法与 Lambda 所实现的函数式接口的抽象方法在参数列表和返回值类型上完全一致时,可以使用方法引用。

# 3. 方法引用的使用格式

方法引用有三种常见格式,具体使用方式如下:

  1. 对象::实例方法
  2. 类::静态方法
  3. 类::实例方法

# 4. 方法引用的使用要求

要使用方法引用,必须满足以下条件:

  1. 函数式接口的抽象方法与方法引用的方法在参数列表和返回值类型上完全一致。 这意味着方法引用必须能够匹配接口中唯一的抽象方法,确保其形参和返回值一致。

  2. 对于 类::实例方法 的情况,函数式接口的第一个参数应当是调用方法的对象,第二个参数是方法的入参(或无参数)。 例如,Comparator<String> 接口中的 compare(T o1, T o2) 方法可以通过 String::compareTo 引用实现,因为第一个参数作为调用者,第二个参数作为入参。

# 5. 方法引用的使用示例

# 1. 对象::实例方法

使用场景: 当 Lambda 表达式中的操作是一个现有对象的实例方法时,可以使用这种方法引用。

示例:

import java.util.function.Consumer;

public class MethodRefExample1 {
    public static void main(String[] args) {
        // 使用 Lambda 表达式实现 Consumer 接口
        Consumer<String> lambdaConsumer = (str) -> System.out.println(str);
        lambdaConsumer.accept("Hello, Lambda!");

        // 使用方法引用实现 Consumer 接口
        PrintStream printStream = System.out; // 获取输出流对象
        Consumer<String> methodRefConsumer = printStream::println; // 方法引用,引用 System.out 对象的 println 方法
        methodRefConsumer.accept("Hello, Method Reference!"); // 输出 "Hello, Method Reference!"
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

函数式接口抽象方法与引用方法的对比:

  • Consumer<String> 接口的 void accept(T t) 方法:
    • 参数:String t
    • 返回值:void
  • 被引用方法 PrintStream.println(String x):
    • 参数:String x
    • 返回值:void

两者的参数列表和返回值类型完全一致,因此可以使用方法引用。

使用要求:

  • 方法引用与函数式接口的抽象方法的参数和返回值类型必须一致。

适用场景: 打印日志、输出信息等。


# 2. 类::静态方法

使用场景: 当 Lambda 表达式中的操作是调用一个静态方法时,可以使用这种方法引用。

示例:

import java.util.Comparator;

public class MethodRefExample2 {
    public static void main(String[] args) {
        // 使用 Lambda 表达式实现 Comparator 接口
        Comparator<Integer> lambdaComparator = (x, y) -> Integer.compare(x, y);
        System.out.println("Lambda Comparator: " + lambdaComparator.compare(3, 7)); // 输出:-1

        // 使用方法引用实现 Comparator 接口
        Comparator<Integer> methodRefComparator = Integer::compare; // 引用 Integer 类的 compare 静态方法
        System.out.println("Method Reference Comparator: " + methodRefComparator.compare(3, 7)); // 输出:-1
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

函数式接口抽象方法与引用方法的对比:

  • Comparator<Integer> 接口的 int compare(T o1, T o2) 方法:
    • 参数:Integer o1, Integer o2
    • 返回值:int
  • 被引用方法 Integer.compare(int x, int y):
    • 参数:int x, int y
    • 返回值:int

两者的参数列表和返回值类型完全一致,因此可以使用方法引用。

使用要求:

  • 静态方法的参数和返回值类型与函数式接口的抽象方法一致。

适用场景: 数值比较、排序操作等。


# 3. 类::实例方法

使用场景: 在我们实现的函数式接口的抽象方法中,可能需要调用其他现有的方法。如果这个抽象方法的第一个参数是我们内部要调用的其他方法的调用者,第二个参数是我们内部调用的方法的参数(或者无参数),那么我们可以直接使用方法引用来简化代码。

示例:

import java.util.Comparator;

public class MethodRefExample3 {
    public static void main(String[] args) {
        // 使用匿名内部类实现 Comparator 接口
        Comparator<String> traditionalComparator = new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.compareTo(s2);
            }
        };
        System.out.println("传统方式比较结果:" + traditionalComparator.compare("abc", "abd")); // 输出:-1

        // 使用 Lambda 表达式实现 Comparator 接口
        Comparator<String> lambdaComparator = (s1, s2) -> s1.compareTo(s2);
        System.out.println("Lambda 表达式比较结果:" + lambdaComparator.compare("abc", "abd")); // 输出:-1

        // 使用方法引用实现 Comparator 接口
        Comparator<String> methodRefComparator = String::compareTo; // 引用 String 类的 compareTo 方法
        System.out.println("方法引用比较结果:" + methodRefComparator.compare("abc", "abd")); // 输出:-1
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

函数式接口抽象方法与引用方法的对比:

  • Comparator<String> 接口的 int compare(T o1, T o2) 方法:
    • 参数:String o1, String o2
    • 返回值:int
  • 被引用方法 String.compareTo(String anotherString):
    • 参数:String anotherString
    • 返回值:int

在这个抽象方法的实现中:

  1. o1 是内部调用的 compareTo 方法的调用者。
  2. o2 是传递给 compareTo 方法的参数。

重要理解点

  • 只有当我们要实现的函数式接口方法中,内部调用了其他方法,并且该调用的第一个参数是方法的调用者,第二个参数是传递的参数时,才能使用这种方法引用。
  • 在这种情况下,Java 编译器可以自动推断出调用关系,我们可以直接使用类名来引用实例方法,而不需要显式地实例化一个对象。

使用要求:

  • 函数式接口的第一个参数是方法的调用者,第二个参数是方法的入参(或没有入参)。
  • 方法引用的参数和返回值类型必须与函数式接口的抽象方法一致。

适用场景: 字符串比较、对象比较等。


# 6. 方法引用的总结和建议

  • 何时使用方法引用: 当 Lambda 表达式中的操作已经有现成的方法实现,并且该方法与函数式接口的抽象方法在参数列表和返回值类型上完全一致时,使用方法引用是更简洁的选择。
  • 如何选择: Lambda 表达式适用于自定义的逻辑或复杂操作,而方法引用适用于直接调用已有方法的情况。两者可以互相替代,但在简单场景中,方法引用更为直观。

通过掌握方法引用的三种常见格式,你可以在实际开发中选择最优的表达方式,使代码更加简洁、易读。

编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08
函数式接口
构造器和数组的引用

← 函数式接口 构造器和数组的引用→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式