Java中的方法引用主要有以下四种类型:1. 静态方法引用格式为 类名::静态方法名 。当需要引用一个类的静态方法时,就可以使用这种形式。例如,对于 Math 类中的 abs 静态方法,可以这样引用:
<1>javaComparator<Integer> comparator = Integer::compare
这 里 Integer::compare 就是对 Integer 类的静态方法 compare 的引用。2. 实例方法引用格式为 对象名::实例方法名 。当需要引用某个特定对象的实例方法时,可以使用这种形式。例如,有一个 User 类,其中有一个 getName 实例方法:
javaComparator<Integer> comparator = Integer::compare;
这里 Integer::compare 就是对 Integer 类的静态方法 compare 的引用。
<2>实例方法引用
格式为 对象名::实例方法名 。当需要引用某个特定对象的实例方法时,可以使用这种形式。例如,有一个 User 类,其中有一个 getName 实例方法:
class User {
private String name;
public User(String name) { this.name = name; }
public String getName() { return name; }
}
User user = new User("Kimi");
Function<User, String> getNameFunction = user::getName;
这里 user::getName 就是对 user 对象的 getName 实例方法的引用。
<3>类方法引用
格式为 类名::实例方法名 。这种引用方式适用于方法的调用者是通过参数传递进来的对象。例如,对于 String 类的 length 方法:
Function<String, Integer> lengthFunction = String::length;
这里 String::length 表示引用 String 类对象的 length 方法,调用时会传入一个 String 对象作为方法的调用者。
<5>构造方法引用
格式为 类名::new 。当需要引用一个类的构造方法时,可以使用这种形式。例如,引用 ArrayList 类的无参构造方法:
javaSupplier<ArrayList> arrayListSupplier = ArrayList::new;
这里 ArrayList::new 就是对 ArrayList 类无参构造方法的引用。
三:方法引用的案例
静态方法引用案例:排序优化假设有一个 Employee 类,其中包含员工的姓名和年龄属性:
javaclass Employee {
private String name;
private int age;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
现在有一个 Employee 对象列表,需要按照年龄进行排序。在Java 8之前,我们可能会这样写:
javaList<Employee> employees = Arrays.asList(new Employee("Alice", 30), new Employee("Bob", 25), new Employee("Charlie", 35));
Collections.sort(employees, new Comparator<Employee>() {
@Override
public int compare(Employee e1, Employee e2) {
return Integer.compare(e1.getAge(), e2.getAge());
}
});
使用Lambda表达式后,可以简化为:
javaemployees.sort((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()));
而使用静态方法引用,代码可以进一步简化为:
javaemployees.sort(Comparator.comparingInt(Employee::getAge));
这里 Comparator.comparingInt(Employee::getAge) 利用了 Comparator 类的 comparingInt 静态方法,通过方法引用 Employee::getAge 来获取员工年龄,然后进行比较排序。这种方式不仅代码更加简洁,而且可读性也更高。2. 实例方法引用案例:数据处理假设有一个 Order 类,表示订单,其中包含订单号和订单金额属性:javaclass Order {
private String orderId;
private double amount;
public Order(String orderId, double amount) {
this.orderId = orderId;
this.amount = amount;
}
public String getOrderId() { return orderId; }
public double getAmount() { return amount; }
}
现在有一个订单列表,需要将订单号提取出来存放到一个新的列表中。传统的方式可能是这样:
javaList<Order> orders = Arrays.asList(new Order("1001", 120.5), new Order("1002", 80.0), new Order("1003", 200.0));
List<String> orderIds = new ArrayList<>();
for (Order order : orders) {
orderIds.add(order.getOrderId());
}
使用Lambda表达式可以简化为:
javaList<String> orderIds = orders.stream().map(order -> order.getOrderId()).collect(Collectors.toList());
而使用实例方法引用,代码可以更简洁地写为:
avaList<String> orderIds = orders.stream().map(Order::getOrderId).collect(Collectors.toList());
这里 Order::getOrderId 直接引用了 Order 类对象的 getOrderId 实例方法,通过流的操作将订单列表中的每个订单的订单号提取出来,最终收集到一个新的列表中。这种方式使得代码更加优雅,也更易于理解和维护3. 类方法引用案例:字符串处理假设有一个字符串列表,需要对其中的每个字符串进行去空格操作。
传统的方式可能是这样:
javaList<String> strings = Arrays.asList(" hello ", " world ", " java ");
List<String> trimmedStrings = new ArrayList<>();
for (String str : strings) {
trimmedStrings.add(str.trim());
}
使用Lambda表达式可以简化为:
javaList<String> trimmedStrings = strings.stream().map(str -> str.trim()).collect(Collectors.toList());
而使用类方法引用,代码可以更简洁地写为:
javaList<String> trimmedStrings = strings.stream().map(String::trim).collect(Collectors.toList());
这里 String::trim 引用了 String 类对象的 trim 方法,通过流的操作对字符串列表中的每个字符串进行去空格处理,最终收集到一个新的列表中。这种方式不仅减少了代码量,而且使得代码的意图更加明确。
- 构造方法引用案例:
对象创建假设有一个 Product 类,表示产品,其中包含产品名称和价格属性:javaclass Product {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() { return name; }
public double getPrice() { return price; }
}
现在有一个包含产品名称和价格的二维数组,需要根据这些数据创建 Product 对象列表。传统的方式可能是这样:
javaString[][] productData = {{"Apple", "10.0"}, {"Banana", "5.0"}, {"Orange", "8.0"}};
List<Product> products = new ArrayList<>();
for (String[] data : productData) {
products.add(new Product(data[0], Double.parseDouble(data[1])));
}
使用Lambda表达式可以简化为:
javaList<Product> products = Arrays.stream(productData).map(data -> new Product(data[0], Double.parseDouble(data[1]))).collect(Collectors.toList());
而使用构造方法引用,代码可以更简洁地写为:
javaList<Product> products = Arrays.stream(productData).map(data -> new Product(data[0], Double.parseDouble(data[1]))).collect(Collectors.toList());
这里 Product::new 引用了 Product 类的构造方法,通过流的操作将二维数组中的每个数据项转换为 Product 对象,最终收集到一个新的列表中。这种方式使得对象的创建过程更加简洁明了。
四:总结
代码简洁:方法引用能够让代码更加简洁,减少冗余的代码,提高代码的可读性和可维护性。
- 语义清晰:方法引用的语法直观地表达了调用某个方法的意图,使得代码的语义更加清晰,易于理解。
- 性能优化:在某些情况下,方法引用可能会比Lambda表达式有更好的性能表现,因为方法引用在编译时就已经确定了具体的调用方法,而Lambda表达式可能需要在运行时进行更多的动态解析。局限性1. 适用场景有限:方法引用只能用于那些符合函数式接口方法签名的场景,如果方法的参数类型、返回类型等与函数式接口不匹配,就无法使用方法引用。2. 灵活性较低:与Lambda表达式相比,方法引用的灵活性较低。Lambda表达式可以包含任意的逻辑,而方法引用只能引用已有的方法,无法在引用时添加额外的逻辑处理。