java语言中方法引用的四种方式(双语翻译)

方法引用

You use lambda expressions to create anonymous methods. Sometimes, however, a lambda expression does nothing but call an existing method. 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.

Consider again the Person class discussed in the section Lambda Expressions:

使用lambda表达式创建匿名方法。然而,有时lambda表达式除了调用现有方法外什么也不做。在这些情况下,通过名称引用现有方法通常会更清楚。方法引用使您能够做到这一点;对于已有名称的方法,它们是紧凑、易于阅读的lambda表达式。

再次考虑lambda表达式一节中讨论的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. Therefore, you could use a lambda expression instead of defining and then creating a new instance of a class that implements Comparator:

请注意,Comparator接口是一个函数式接口。因此,你可以使用lambda表达式,而不是定义然后创建一个实现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. You can invoke this method instead in the body of the lambda expression:

然而,这种比较两个Person实例出生日期的方法已经存在,即Person. comparebyage。你可以在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). Each has the following characteristics:

  • Its formal parameter list is copied from Comparator<Person>.compare, which is (Person, Person).
  • Its body calls the method Person.compareByAge.

方法引用Person::compareByAge在语义上与lambda表达式(a, b) -> Person.compareByAge(a, b)。它们都有以下特点:

-它的形式参数列表是从 Comparator<Person>.compare复制过来的,它是(Person, Person)

-它的主体调用了Person.compareByAge方法。

方法引用的种类

There are four kinds of method references:

有四种方法引用:

KindSyntaxExamples
Reference to a static method指向静态方法的引用*ContainingClass*::*staticMethodName*Person::compareByAge MethodReferencesExamples::appendStrings
Reference to an instance method of a particular object引用特定对象的实例方法*containingObject*::*instanceMethodName*myComparisonProvider::compareByName myApp::appendStrings2
Reference to an instance method of an arbitrary object of a particular type引用特定类型任意对象的实例方法*ContainingType*::*methodName*String::compareToIgnoreCase String::concat
Reference to a constructor对构造函数的引用*ClassName*::newHashSet::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: Hello World!

BiFunction is one of many functional interfaces in the java.util.function package. The BiFunction functional interface can represent a lambda expression or method reference that accepts two arguments and produces a result.

所有System.out.println()语句输出相同的内容:’ Hello World!`

BiFunctionjava.util.function包中的函数式接口之一。BiFunction函数接口可以表示一个接受两个参数并产生结果的lambda表达式或方法引用。

引用静态方法

The method references Person::compareByAge and MethodReferencesExamples::appendStrings are references to a static method.

方法引用Person::compareByAgeMethodReferencesExamples::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. The JRE infers the method type arguments, which in this case are (Person, Person).

Similarly, the method reference myApp::appendStrings2 invokes the method appendStrings2 that is part of the object myApp. The JRE infers the method type arguments, which in this case are (String, String).

方法引用myComparisonProvider::compareByName调用了compareByName方法,该方法是对象myComparisonProvider的一部分。JRE推断出方法的类型参数,在本例中为(Person, Person)

类似地,方法引用myApp::appendStrings2会调用对象myApp中的appendStrings2方法。JRE推断方法类型参数,在本例中为(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. The method reference would invoke the method a.compareToIgnoreCase(b).

Similarly, the method reference String::concat would invoke the method a.concat(b).

方法引用String::compareToIgnoreCase等效的lambda表达式具有正式的参数列表(String a, String b),其中ab是为了更好地描述这个示例而使用的任意名称。方法引用将调用方法a.compareToIgnoreCase(b)

类似地,方法引用String::concat将调用方法a.concat(b)

对构造函数的引用

You can reference a constructor in the same way as a static method by using the name new. The following method copies elements from one collection to another:

你可以像引用静态方法一样使用new来引用构造函数。下面的方法将元素从一个集合复制到另一个集合:

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. Consequently, you can invoke the method transferElements with a lambda expression as follows:

函数式接口Supplier包含一个没有参数并返回一个对象的方法get。因此,你可以使用lambda表达式调用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 HashSet collection that contains elements of type Person. Alternatively, you can specify this as follows:

Java编译器推断出你想要创建一个包含类型为Person的元素的HashSet集合。或者,你也可以这样指定:

Set<Person> rosterSet = transferElements(roster, HashSet<Person>::new);

翻译自Oracle官网的java文档教程,原文链接:https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值