Java方法引用是Java 8引入的一项重要特性,它提供了一种简洁、可读性高的方式来直接引用已经存在的方法。方法引用使得代码更加简洁、易懂,同时提高了代码的可维护性和重用性。本文将详细介绍Java方法引用的概念、语法和使用方法,并提供一些示例代码。
方法引用是一种直接引用已经存在的方法的方式,它允许我们在代码中通过方法的名称来引用方法。方法引用可以被看作是Lambda表达式的一种简化形式,它提供了一种更加简洁的方式来实现函数式接口。
在Java中,方法引用主要用于简化函数式接口的实现,特别是当我们需要将一个方法作为参数传递给另一个方法时,使用方法引用可以使代码更加清晰。
方法引用的语法由两部分组成:类名或对象名和方法名,中间使用双冒号(::)进行分隔。根据方法引用的情况,可以分为以下几种形式:
类名::静态方法名
对象名::实例方法名
类名::实例方法名
类名::new
使用类名和双冒号(::)来引用一个静态方法。例如,Math::max
表示引用Math类中的静态max方法。
Weigher integerIntegerWeigher = Math::max;
使用实例对象和双冒号(::)来引用一个非静态的实例方法。例如,String::length
表示引用String对象的length方法。
LineHandler lineHandler = String::length;
使用特定对象的实例和双冒号(::)来引用该对象的实例方法。例如,myObject::methodName
表示引用myObject对象的methodName方法。
Student student = new Student();
Copier getUsername = student::getUsername;
Copier arrayListCopier = ArrayList::new;
方法引用主要用于函数式接口,即只包含一个抽象方法的接口。函数式接口可以使用方法引用来实现抽象方法,从而实现相应的功能。
Java中提供了许多函数式接口,如Consumer
、Predicate
、Supplier
等。可以使用方法引用来简化这些接口的实现,使代码更加简洁、易读。
下面是一些方法引用的使用示例:
Consumer
接口List 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就是函数式接口
Supplier
接口Supplier> listSupplier = ArrayList::new;
List names = listSupplier.get();
Supplier也是函数式接口(源码)
@FunctionalInterface
public interface Supplier {
/**
* 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);
}
@Override
public String toString() {
return "Vehicle{" +
"type='" + type + '\'' +
'}';
}
}
public class MethodReferenceExample {
public static void main(String[] args) {
// 静态方法引用: 类名::静态方法
List names = Arrays.asList("擎天柱", "霸天虎", "威震天");
names.forEach(Vehicle::printName);
System.out.println();
// 实例方法引用: 对象名::实例方法
Vehicle example = new Vehicle();
List messages = Arrays.asList(50000L, 120000L);
messages.forEach(example::printPowerValue);
System.out.println();
// 构造方法引用: 类名::new
Supplier 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 suffixes = Arrays.asList("A", "B", "C");
suffixes.stream()
.map(prefix::concat) // 使用String的concat方法
.forEach(System.out::println); // 使用System.out的println方法
}
}
在这个示例中,我们使用了静态方法引用、实例方法引用、构造方法引用和引用特定类型的任意对象的实例方法。通过运行这个程序,可以看到各个方法引用形式的使用效果。
运行结果:
擎天柱
霸天虎
威震天
50000
120000
Vehicle{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博客
在使用方法引用时,有一些注意事项需要考虑
参考文章:【Java基础教程】(二十八)Java新特性篇 · 第八讲:方法引用——概念及优缺点、语法形式及使用案例、应用场景与注意事项 ~_java方法引用重要吗-CSDN博客
【Java 基础篇】Java方法引用详解-CSDN博客