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表达式,从而进步了可读性并说明编程的用意。
如果你感觉文章还不错,记得关注公众号: 锅外的大佬
锅外的大佬博客