1. 引言
Java8 中最受宽广开发中喜爱的变动之一是因为引入了 lambda 表达式,因为这些表达式容许咱们放弃匿名类,从而大大减少了样板代码,并进步了可读性。
办法援用是 lambda 表达式的一种非凡类型。它们通常通过援用现有办法来创立简略的 lambda 表达式。
办法援用包含以下四种类型:
- 静态方法
- 特定对象的实例办法
- 特定类型的任意对象的实例办法
- 构造方法
在本篇文章中,咱们将探讨 Java 中的办法援用。
2. 援用静态方法
We’ll begin with a very simple example, capitalizing and printing a list of Strings:
咱们从一个非常简单的示例开始,字符串转成大写并打印:
List<String> messages = Arrays.asList("hello", "baeldung", "readers!");
咱们能够通过简略的 lambda 表达式间接调用 StringUtils.capitalize()
办法:
messages.forEach(word -> StringUtils.capitalize(word));
或者,咱们能够应用办法援用来简略地援用 capitalize
静态方法:
messages.forEach(StringUtils::capitalize);
留神,办法援用应应用 ::
运算符。
3. 援用特定对象的实例办法
为了演示这种类型的办法援用,咱们新建以下这两个类:
public class Bicycle {
private String brand;
private Integer frameSize;
// standard constructor, getters and setters
}
public class BicycleComparator implements Comparator {
@Override
public int compare(Bicycle a, Bicycle b) {return a.getFrameSize().compareTo(b.getFrameSize());
}
}
创立一个 BicycleComparator 对象来比拟自行车尺寸:
BicycleComparator bikeFrameSizeComparator = new BicycleComparator();
咱们能够应用 lambda 表达式按尺寸大小对自行车进行排序,但须要指定两个自行车实例进行比拟:
createBicyclesList().stream()
.sorted((a, b) -> bikeFrameSizeComparator.compare(a, b));
咱们能够应用办法援用让编译器把句柄参数传递给咱们:
createBicyclesList().stream()
.sorted(bikeFrameSizeComparator::compare);
4. 援用特定类型任意对象的实例办法
这种类型的办法援用与后面的示例相似,但不用创立自定义对象来执行比拟。
让咱们创立一个要排序的Integer 整数列表:
List<Integer> numbers = Arrays.asList(5, 3, 50, 24, 40, 2, 9, 18);
如果咱们应用经典的 lambda 表达式,这两个参数都须要显式传递,而应用办法援用则要简略得多:
numbers.stream()
.sorted((a, b) -> a.compareTo(b));
numbers.stream()
.sorted(Integer::compareTo);
只管它依然是一行代码,然而办法援用更容易浏览和了解。
5. 援用构造函数
咱们能够像在第一个例子中援用静态方法一样援用构造函数。惟一区别是须要应用 new 关键字。
当初咱们用不同品牌的 String 列表创立一个 Bicycle 数组:
List<String> bikeBrands = Arrays.asList("Giant", "Scott", "Trek", "GT");
首先,咱们将向 Bicycle 类增加一个新的构造函数:
public Bicycle(String brand) {
this.brand = brand;
this.frameSize = 0;
}
接下来,咱们将应用办法援用中的新构造函数,并从原始的 String 列表中生成一个 Bicycle 数组:
bikeBrands.stream()
.map(Bicycle::new)
.toArray(Bicycle[]::new);
留神如何应用办法援用调用 Bicycle 和Array构造函数,从而使代码看起来更加简洁明了。
6. 其余示例和限度
目前为止,办法援用是一个使代码十分清晰和易读的好办法。然而,咱们不能用它们来代替各种 lambda 表达式,因为它们有一些局限性。
它们的次要局限性是因为它们最大的长处:前一个表达式的输入须要与援用的办法申明的输出参数匹配。
看看这个限度的例子:
createBicyclesList().forEach(b -> System.out.printf(
"Bike brand is'%s'and frame size is'%d'%n",
b.getBrand(),
b.getFrameSize()));
这个简略的例子不能用办法援用来示意,因为在咱们的例子中,printf 办法须要 3 个参数,而应用 createBicyclesList().forEach() 只容许办法援用一个参数(Bicycle对象)。
最初,咱们钻研下,如何创立一个能够从 lambda 表达式援用的 no-operation 函数。
在本例中,咱们心愿应用 lambda 表达式而不应用其参数。
首先,创立 doNothingAtAll 办法:
private static <T> void doNothingAtAll(Object... o) {}
因为这是一个 varargs 办法,它可执行在任意 lambda 表达式中,而不论援用的对象或参数的数量。咱们看看它的作用:
createBicyclesList()
.forEach((o) -> MethodReferenceExamples.doNothingAtAll(o));
7. 总结
在这篇文章中,咱们学习了 Java 中的办法援用,以及如何应用它们来替换 lambda 表达式,从而进步了可读性并说明编程的用意。
如果你感觉文章还不错,记得关注公众号:锅外的大佬
锅外的大佬博客