The Java Tutorials have been written for JDK 8.Java教程是为JDK 8编写的。Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available.本页中描述的示例和实践没有利用后续版本中引入的改进,并且可能使用不再可用的技术。See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases.有关Java SE 9及其后续版本中更新的语言特性的摘要,请参阅Java语言更改。
See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.有关所有JDK版本的新功能、增强功能以及已删除或不推荐的选项的信息,请参阅JDK发行说明。
You use lambda expressions to create anonymous methods.使用lambda表达式创建匿名方法。Sometimes, however, a lambda expression does nothing but call an existing method.但是,有时lambda表达式只调用现有方法。In those cases, it's often clearer to refer to the existing method by name.在这些情况下,按名称引用现有方法通常更清晰。Method references enable you to do this; they are compact, easy-to-read lambda expressions for methods that already have a name.方法引用使您能够做到这一点;对于已经有名称的方法,它们是紧凑、易于阅读的lambda表达式。
Consider again the 再次考虑lambda表达式节中讨论的Person
class discussed in the section Lambda Expressions:Person
类:
public class Person { // ... LocalDate birthday; public int getAge() { // ... } public LocalDate getBirthday() { return birthday; } public static int compareByAge(Person a, Person b) { return a.birthday.compareTo(b.birthday); } // ... }
Suppose that the members of your social networking application are contained in an array, and you want to sort the array by age.假设社交网络应用程序的成员包含在一个数组中,并且希望按年龄对数组进行排序。You could use the following code (find the code excerpts described in this section in the example 您可以使用以下代码(在示例MethodReferencesTest
):MethodReferencesTest
中找到本节中描述的代码摘录):
Person[] rosterAsArray = roster.toArray(new Person[roster.size()]); class PersonAgeComparator implements Comparator<Person> { public int compare(Person a, Person b) { return a.getBirthday().compareTo(b.getBirthday()); } } Arrays.sort(rosterAsArray, new PersonAgeComparator());
The method signature of this invocation of 此sort
is the following:sort
调用的方法签名如下所示:
static <T> void sort(T[] a, Comparator<? super T> c)
Notice that the interface 请注意,接口Comparator
is a functional interface.Comparator
是一个功能接口。Therefore, you could use a lambda expression instead of defining and then creating a new instance of a class that implements 因此,您可以使用lambda表达式,而不是定义然后创建实现Comparator
:Comparator
的类的新实例:
Arrays.sort(rosterAsArray, (Person a, Person b) -> { return a.getBirthday().compareTo(b.getBirthday()); } );
However, this method to compare the birth dates of two 但是,此用于比较两个Person
instances already exists as Person.compareByAge
.Person
实例的出生日期的方法已作为Person.compareByAge
存在。You can invoke this method instead in the body of the lambda expression:您可以在lambda表达式的主体中调用此方法:
Arrays.sort(rosterAsArray, (a, b) -> Person.compareByAge(a, b) );
Because this lambda expression invokes an existing method, you can use a method reference instead of a lambda expression:由于此lambda表达式调用现有方法,因此可以使用方法引用而不是lambda表达式:
Arrays.sort(rosterAsArray, Person::compareByAge);
The method reference 引用Person::compareByAge
is semantically the same as the lambda expression (a, b) -> Person.compareByAge(a, b)
.Person::compareByAge
的方法在语义上与lambda表达式(a, b) -> Person.compareByAge(a, b)
相同。Each has the following characteristics:每一种都有以下特点:
Comparator<Person>.compare
, which is (Person, Person)
.Comparator<Person>.compare
复制的,即(Person, Person)
。Person.compareByAge
.Person.compareByAge
。There are four kinds of method references:有四种方法参考:
ContainingClass::staticMethodName |
Person::compareByAge MethodReferencesExamples::appendStrings | |
containingObject::instanceMethodName |
myComparisonProvider::compareByName myApp::appendStrings2 | |
ContainingType::methodName |
String::compareToIgnoreCase String::concat | |
ClassName::new |
HashSet::new |
The following example, 以下示例MethodReferencesExamples
, contains examples of the first three types of method references:MethodReferencesExamples
包含前三种方法引用的示例:
import java.util.function.BiFunction; public class MethodReferencesExamples { public static <T> T mergeThings(T a, T b, BiFunction<T, T, T> merger) { return merger.apply(a, b); } public static String appendStrings(String a, String b) { return a + b; } public String appendStrings2(String a, String b) { return a + b; } public static void main(String[] args) { MethodReferencesExamples myApp = new MethodReferencesExamples(); // Calling the method mergeThings with a lambda expression System.out.println(MethodReferencesExamples. mergeThings("Hello ", "World!", (a, b) -> a + b)); // Reference to a static method System.out.println(MethodReferencesExamples. mergeThings("Hello ", "World!", MethodReferencesExamples::appendStrings)); // Reference to an instance method of a particular object System.out.println(MethodReferencesExamples. mergeThings("Hello ", "World!", myApp::appendStrings2)); // Reference to an instance method of an arbitrary object of a // particular type System.out.println(MethodReferencesExamples. mergeThings("Hello ", "World!", String::concat)); } }
All the 所有System.out.println()
statements print the same thing:System.out.println()
语句都打印相同的内容:Hello World!
BiFunction is one of many functional interfaces in the java.util.function package.BiFunction是java.util.function包中许多函数接口之一。The BiFunction
functional interface can represent a lambda expression or method reference that accepts two arguments and produces a result.BiFunction
函数接口可以表示接受两个参数并生成结果的lambda表达式或方法引用。
The method references 该方法引用Person::compareByAge
and MethodReferencesExamples::appendStrings
are references to a static method.Person::compareByAge
和MethodReferencesExamples::appendStrings
是对静态方法的引用。
The following is an example of a reference to an instance method of a particular object:以下是对特定对象的实例方法的引用示例:
class ComparisonProvider { public int compareByName(Person a, Person b) { return a.getName().compareTo(b.getName()); } public int compareByAge(Person a, Person b) { return a.getBirthday().compareTo(b.getBirthday()); } } ComparisonProvider myComparisonProvider = new ComparisonProvider(); Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);
The method reference 方法引用myComparisonProvider::compareByName
invokes the method compareByName
that is part of the object myComparisonProvider
.myComparisonProvider::compareByName
调用作为对象myComparisonProvider
一部分的方法compareByName
。The JRE infers the method type arguments, which in this case are JRE推断方法类型参数,在本例中为(Person, Person)
.(Person, Person)
。
Similarly, the method reference 类似地,方法引myApp::appendStrings2
invokes the method appendStrings2
that is part of the object myApp
.myApp::appendStrings2
调用作为对象myApp
一部分的方法appendStrings2
。The JRE infers the method type arguments, which in this case are JRE推断方法类型参数,在本例中为(String, String)
.(String, String)
。
The following is an example of a reference to an instance method of an arbitrary object of a particular type:以下是对特定类型的任意对象的实例方法的引用示例:
String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" }; Arrays.sort(stringArray, String::compareToIgnoreCase);
The equivalent lambda expression for the method reference 方法引用String::compareToIgnoreCase
would have the formal parameter list (String a, String b)
, where a
and b
are arbitrary names used to better describe this example.String::compareToIgnoreCase
的等效lambda表达式将具有形式参数列表(String a, String b)
,其中a
和b
是用于更好地描述此示例的任意名称。The method reference would invoke the method 方法引用将调用方法a.compareToIgnoreCase(b)
.a.compareToIgnoreCase(b)
。
Similarly, the method reference 类似地,方法引用String::concat
would invoke the method a.concat(b)
.String::concat
将调用方法a.concat(b)
。
You can reference a constructor in the same way as a static method by using the name 您可以使用名称new
.new
以与静态方法相同的方式引用构造函数。The following method copies elements from one collection to another:以下方法将元素从一个集合复制到另一个集合:
public static <T, SOURCE extends Collection<T>, DEST extends Collection<T>> DEST transferElements( SOURCE sourceCollection, Supplier<DEST> collectionFactory) { DEST result = collectionFactory.get(); for (T t : sourceCollection) { result.add(t); } return result; }
The functional interface 函数接口Supplier
contains one method get
that takes no arguments and returns an object.Supplier
包含一个方法get
,该方法不接受任何参数并返回一个对象。Consequently, you can invoke the method 因此,您可以使用lambda表达式调用方法transferElements
with a lambda expression as follows:transferElements
,如下所示:
Set<Person> rosterSetLambda = transferElements(roster, () -> { return new HashSet<>(); });
You can use a constructor reference in place of the lambda expression as follows:可以使用构造函数引用代替lambda表达式,如下所示:
Set<Person> rosterSet = transferElements(roster, HashSet::new);
The Java compiler infers that you want to create a Java编译器推断您想要创建包含HashSet
collection that contains elements of type Person
.Person
类型元素的HashSet
集合。Alternatively, you can specify this as follows:或者,您可以按如下方式指定:
Set<Person> rosterSet = transferElements(roster, HashSet<Person>::new);