【Java 干货教程】Java方法引用详解

导言

Java方法引用是Java 8引入的一项重要特性,它提供了一种简洁、可读性高的方式来直接引用已经存在的方法。方法引用使得代码更加简洁、易懂,同时提高了代码的可维护性和重用性。本文将详细介绍Java方法引用的概念、语法和使用方法,并提供一些示例代码。

一、方法引用的概念

方法引用是一种直接引用已经存在的方法的方式,它允许我们在代码中通过方法的名称来引用方法。方法引用可以被看作是Lambda表达式的一种简化形式,它提供了一种更加简洁的方式来实现函数式接口。

在Java中,方法引用主要用于简化函数式接口的实现,特别是当我们需要将一个方法作为参数传递给另一个方法时,使用方法引用可以使代码更加清晰。

二、方法引用的语法

方法引用的语法由两部分组成:类名或对象名和方法名,中间使用双冒号(::)进行分隔。根据方法引用的情况,可以分为以下几种形式:

  • 静态方法引用:类名::静态方法名
  • 实例方法引用:对象名::实例方法名
  • 特定类的任意对象方法引用:类名::实例方法名
  • 构造方法引用:类名::new

 2.1、静态方法引用

使用类名和双冒号(::)来引用一个静态方法。例如,Math::max表示引用Math类中的静态max方法。

Weigher<Integer, Integer> integerIntegerWeigher = Math::max;

2.2、实例方法引用

使用实例对象和双冒号(::)来引用一个非静态的实例方法。例如,String::length表示引用String对象的length方法。

LineHandler lineHandler = String::length;

2.3、特定类的任意对象方法引用

使用特定对象的实例和双冒号(::)来引用该对象的实例方法。例如,myObject::methodName表示引用myObject对象的methodName方法。

Student student = new Student();
Copier<String> getUsername = student::getUsername;

2.4、构造方法引用

Copier<ArrayList> arrayListCopier = ArrayList::new;

三、方法引用的使用方法

方法引用主要用于函数式接口,即只包含一个抽象方法的接口。函数式接口可以使用方法引用来实现抽象方法,从而实现相应的功能。

Java中提供了许多函数式接口,如ConsumerPredicateSupplier等。可以使用方法引用来简化这些接口的实现,使代码更加简洁、易读。

下面是一些方法引用的使用示例:

3.1、使用方法引用实现Consumer接口

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.forEach(System.out::println);

forEach()方法源码

default void forEach(Consumer<? super T> action) {Objects.requireNonNull(action);for (T t : this) {action.accept(t);}}

这里的Consumer就是函数式接口

3.2、使用方法引用实现Supplier接口

Supplier<List<String>> listSupplier = ArrayList::new;
List<String> names = listSupplier.get();

Supplier也是函数式接口(源码)

@FunctionalInterface
public interface Supplier<T> {/*** Gets a result.** @return a result*/T get();
}

四、案例 

以下是一个示例Java程序,演示了Java方法引用的四种使用形式:

import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;class Vehicle {private String type;public String getType() {return type;}public void setType(String type) {this.type = type;}// 静态方法public static void printName(String name) {System.out.println(name);}// 实例方法public void printPowerValue(Long powerValue) {System.out.println(powerValue);}@Overridepublic String toString() {return "Vehicle{" +"type='" + type + '\'' +'}';}
}public class MethodReferenceExample {public static void main(String[] args) {// 静态方法引用: 类名::静态方法List<String> names = Arrays.asList("擎天柱", "霸天虎", "威震天");names.forEach(Vehicle::printName);System.out.println();// 实例方法引用: 对象名::实例方法Vehicle example = new Vehicle();List<Long> messages = Arrays.asList(50000L, 120000L);messages.forEach(example::printPowerValue);System.out.println();// 构造方法引用: 类名::newSupplier<Vehicle> vehicleSupplier = Vehicle::new;// 创建对象Vehicle car = vehicleSupplier.get();car.setType("Car");Vehicle bike = vehicleSupplier.get();bike.setType("Bike");// 打印对象System.out.println(car);System.out.println(bike);System.out.println();// 引用特定类型的任意对象的实例方法: 对象名::实例方法String prefix = "Prefix:";List<String> suffixes = Arrays.asList("A", "B", "C");suffixes.stream().map(prefix::concat) // 使用String的concat方法.forEach(System.out::println); // 使用System.out的println方法}
}

在这个示例中,我们使用了静态方法引用、实例方法引用、构造方法引用和引用特定类型的任意对象的实例方法。通过运行这个程序,可以看到各个方法引用形式的使用效果。

运行结果:

擎天柱
霸天虎
威震天50000
120000Vehicle{type='Car'}
Vehicle{type='Bike'}Prefix:A
Prefix:B
Prefix:C

五、应用场景

方法引用广泛应用于函数式编程、Stream API和Lambda表达式等方面,特别在以下几个场景中被普遍使用:

1. 集合操作:在集合的排序、筛选、映射等操作时,可以使用方法引用简化代码;
2. GUI编程:在事件处理、回调函数等方面,通过方法引用来实现事件的响应机制;
3. 数据处理:在对数据进行加工、处理和计算时,方法引用常用于替代复杂的Lambda表达式。

想了解Stream API 和Lambda表达式和方法引用的场景可以看看我的这篇文章

【Java干货教程】Stream流详解-CSDN博客

六、注意事项

在使用方法引用时,有一些注意事项需要考虑

  1. 方法引用只能用于函数式接口:方法引用只能用于那些只有一个抽象方法的接口,也就是函数接口。确保在使用方法引用时,目标类型是一个函数接口,否则编译将会失败。
  2. 参数匹配:方法引用的参数必须与目标方法的参数列表兼容。这意味着参数数量和类型要一致。如果目标方法具有多个参数,可以通过上下文推断或者函数式接口的泛型来进行类型匹配。(方法引用的方法签名必须与函数式接口的抽象方法的参数列表和返回类型一致
  3. 方法引用可能引发空指针异常:在使用实例方法引用时,请确保对象引用不是null。否则,在调用实例方法时会引发空指针异常。因此,在进行实例方法引用操作前,请先对对象进行必要的空值检查。
  4. 正确使用方法引用,增加代码可读性:正确使用方法引用可以使代码更加简洁、清晰和易于理解。然而,过度使用方法引用可能会导致代码难以阅读和维护。请在合适的情况下使用方法引用,并在需要更明确的表达时使用传统的Lambda表达式(或匿名类)来代替。
  5. 选择最适合的方法引用方式:熟悉各种方法引用的不同形式,包括静态方法引用、实例方法引用、构造方法引用和引用特定类型的任意对象的实例方法。了解这些不同的使用形式,可以根据具体的编码需求选择最适合的方法引用方式。(方法引用不能直接引用抽象方法,也不能引用接口中的默认方法
  6. 方法引用与Lambda表达式的比较:在某些情况下,方法引用可以代替Lambda表达式来提高代码可读性。然而,并非所有情况都适合使用方法引用。有时,使用Lambda表达式可能更清晰明了。

七、优势和缺点

7.1、优点

  • 简化代码:方法引用可以将一些复杂的Lambda表达式转化为简洁明了的代码;
  • 提高代码的复用性:通过方法引用,我们可以重复使用已经存在的方法,而无需重复编写相同的代码。

7.2、缺点 

  • 可读性限制:某些情况下,过多的方法引用可能会降低代码的可读性,特别是当方法名并不直观或者存在多个参数的情况下;
  • 局限性:方法引用只能用于引用非静态方法、静态方法和构造方法(静态方法引用、实例方法引用、构造方法引用和引用特定类型的任意对象的实例方法),对于其他情况则无法使用(不能直接引用抽象方法,也不能引用接口中的默认方法)。

参考文章:【Java基础教程】(二十八)Java新特性篇 · 第八讲:方法引用——概念及优缺点、语法形式及使用案例、应用场景与注意事项 ~_java方法引用重要吗-CSDN博客

【Java 基础篇】Java方法引用详解-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/622567.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

超详细的 pytest 钩子函数 之初始钩子和引导钩子来啦

前几篇文章介绍了 pytest 点的基本使用&#xff0c;学完前面几篇的内容基本上就可以满足工作中编写用例和进行自动化测试的需求。从这篇文章开始会陆续给大家介绍 pytest 中的钩子函数&#xff0c;插件开发等等。 仔细去看过 pytest 文档的小伙伴&#xff0c;应该都有发现 pyte…

【数据结构 | 希尔排序法】

希尔排序法 思路ShellSort 思路 希尔排序法又称缩小增量法。希尔排序法的基本思想是&#xff1a;先选定一个整数&#xff0c;把待排序文件中所有记录分成个组&#xff0c;所有距离为的记录分在同一组内&#xff0c;并对每一组内的记录进行排序。然后&#xff0c;取&#xff0c…

关于Golang闭包

关于Golang闭包 1、能不用闭包的地方就不要用闭包&#xff0c;没必要为了炫技&#xff0c;写一段增加团队小伙伴负担的代码 2、for 循环代码&#xff0c;统一在内部用临时变量再存一下 for _, val : range values {val : val }在线代码演示&#xff1a;https://go.dev/play/p…

docker 支持 gpu

需求&#xff1a; 原先在宿主机里运行的服务需要迁移到docker 里 进程&#xff1a; docker 支持 gpu 需要装toolkit &#xff0c;但是正常情况下没有对应的源&#xff0c;所以先引入源文件 distribution$(. /etc/os-release;echo $ID$VERSION_ID) \ && curl -fsSL …

ospf-gre隧道小练习

全网可达,R5路由表没有其他路由器的路由条目 注:每个路由器都添加了自己的环回,如R1就是1.1.1.1 R1可以分别ping通与R2,R3,R4之间的隧道 R1路由表上有所有路由器环回的路由条目 R5路由表上没有其他路由器的路由条目 实现代码: 首先将各个接口IP配好 边上3个路由器:[R6][R7][R…

ES API 批量操作 Bulk API

bulk 是 elasticsearch 提供的一种批量增删改的操作API。 bulk 对 JSON串 有着严格的要求。每个JSON串 不能换行 &#xff0c;只能放在同一行&#xff0c;同时&#xff0c; 相邻的JSON串之间必须要有换行 &#xff08;Linux下是\n&#xff1b;Window下是\r\n&#xff09;。bul…

【谭浩强C程序设计 学习辅导第3章】最简单的C程序设计——顺序程序设计(含详细源码)

文章目录 一、 顺序程序设计题的解题思路及注意事项解题思路注意事项 二、源码讲解第3章源码文件构成&#xff1a;main.c 文件内容说明chap3.c源码实现chap3.h声明头文件测试结果展示源码链接 说明&#xff1a;本学习辅导题适用于谭浩强教辅第四版。 一、 顺序程序设计题的解题…

学习记录————

1月 1月10号 习惯这件事很重要&#xff0c;一个长期坚守的习惯不一定是最好的&#xff0c;但是是能一直坚守下去的。所以习惯不能变来变去 长期坚守的习惯是什么&#xff1f;①10点 && (视频后 || 聊完天后)两个小时学习。②上床不玩手机。③周末&#xff1a;10-12点…

Programming Abstractions in C阅读笔记:p246-p247

《Programming Abstractions in C》学习第68天&#xff0c;p246-p247总结&#xff0c;总计2页。 一、技术总结 本章通过“the game of nim(尼姆游戏)”&#xff0c;这类以现实生活中事物作为例子进行讲解的情况&#xff0c;往往对学习者要求比较高&#xff0c;需要学习者具备…

<软考高项备考>《论文专题 - 65 质量管理(4) 》

4 过程3-管理质量 4.1 问题 4W1H过程做什么为了评估绩效&#xff0c;确保项目输出完整、正确且满足客户期望&#xff0c;而监督和记录质量管理活动执行结果的过程作用&#xff1a;①核实项目可交付成果和工作已经达到主要干系人的质量要求&#xff0c;可供最终验收;②确定项目…

C# 静态代码织入AOP组件之肉夹馍

写在前面 关于肉夹馍组件的官方介绍说明&#xff1a; Rougamo是一个静态代码织入的AOP组件&#xff0c;同为AOP组件较为常用的有Castle、Autofac、AspectCore等&#xff0c;与这些组件不同的是&#xff0c;这些组件基本都是通过动态代理IoC的方式实现AOP&#xff0c;是运行时…

linux系统中线程(Thread)解读以及对IO性能的影响

线程是操作系统调度的基本单位&#xff0c;是进程中能够独立执行指令流的子任务。在线程模型中&#xff0c;多个线程共享同一进程的地址空间和其他资源&#xff0c;使得它们可以直接访问相同的内存区域&#xff0c;这样大大简化了数据共享和通信的复杂性。线程有以下几个关键特…

【Web】CTFSHOW PHP特性刷题记录(全)

知其然知其所以然&#xff0c;尽量把每种特性都详细讲明白。 目录 web89 web90 web91 web92 web93 web94 web95 web96 web97 web98 web99 web100 web101 web102 web103 web104 web105 web106 web107 web108 web109 web110 web111 web112 web113 web…

高级分布式系统-第12讲 分布式控制经典理论

控制器基础 分布式控制系统的设计&#xff0c;是指在给定系统性能指标的条件下&#xff0c;设计出控制器的控制规律和相应的数字控制算法。 PID控制器 根据偏差的比例&#xff08;Proportional&#xff09;、积分&#xff08;Integral&#xff09;、微分&#xff08;Derivati…

SQL_DCL_管理用户

DCL英文全称 Data Control Language(数据控制语言&#xff0c;用来管理数据库用户&#xff0c;控制数据库的访问权限。 1.查询用户 USE MY SQL; SELECT * FROM USER; 2.创建用户 CREATE USER 用户名主机名 IDENTIFIED BY密码; 3.修改用户密码 ALTER USER 用户名 主机名 …

Android修改Spinner默认文字颜色

要修改Spinner&#xff08;下拉选择框&#xff09;的默认文字颜色&#xff0c;你可以使用自定义的Spinner适配器&#xff0c;并重写getView()方法来设置文字颜色。以下是一个示例&#xff1a; 创建一个自定义的Spinner适配器类&#xff08;继承自ArrayAdapter) class CustomSp…

工作压力测试

每个职场人都会遇到工作压力&#xff0c;在企业人力资源管理的角度来看&#xff0c;没有工作压力是人力资源的低效&#xff0c;适当的工作压力可以促使员工不断进取&#xff0c;然而每个人的抗压能力是不同的&#xff0c;同样的工作量和工作难度&#xff0c;不同的人在面对相同…

编程探秘:Python深渊之旅-----云端部署(六)

为了提高可访问性和性能&#xff0c;团队决定将他们的应用部署到云平台。龙带领团队探索不同的云服务提供商和部署策略。 龙&#xff08;自信地&#xff09;&#xff1a;将我们的应用部署到云端是一个明智的决策。云计算不仅提供可扩展性&#xff0c;还能让我们的应用全天候运…

ORB-SLAM2重要函数总结(1)——特征点、地图点、关键帧

ORB-SLAM2重要函数总结&#xff08;1&#xff09; ORBFeature IC_Angle通过遍历特征点周围的像素&#xff0c;利用灰度质心法来计算特征点的角度朝向。具体地&#xff0c;它根据像素值和像素坐标的加权和来计算方向角度&#xff0c;使特征点具有旋转不变性。computeOrientati…

k8s实战从入门到上天系列第一篇:K8s微服务实战内容开篇介绍

前言 我们使用开源ruoyi微服务基本使用&#xff0c;基于基本的微服务实践。我们来讲解k8s的实战内容。 第一章&#xff1a;开源ruoyi微服务简介基本使用 第二章&#xff1a;k8s基本知识回顾、k3s集群搭建和基本使用 第三章&#xff1a;微服务镜像构建 第四章&#xff1a;中间件…