java 方法引用_JAVA 8 方法引用 - Method References

什么是方法引用

简单地说,就是一个Lambda表达式。在Java 8中,我们会使用Lambda表达式创建匿名方法,但是有时候,我们的Lambda表达式可能仅仅调用一个已存在的方法,而不做任何其它事,对于这种情况,通过一个方法名字来引用这个已存在的方法会更加清晰,Java 8的方法引用允许我们这样做。方法引用是一个更加紧凑,易读的Lambda表达式,注意方法引用是一个Lambda表达式,其中方法引用的操作符是双冒号"::"。

方法引用例子

先看一个例子

首先定义一个Person类,如下:

packagemethodreferences;importjava.time.LocalDate;public classPerson

{publicPerson(String name, LocalDate birthday)

{this.name =name;this.birthday =birthday;

}

String name;

LocalDate birthday;publicLocalDate getBirthday()

{returnbirthday;

}public static intcompareByAge(Person a, Person b)

{returna.birthday.compareTo(b.birthday);

}

@OverridepublicString toString()

{return this.name;

}

}

假设我们有一个Person数组,并且想对它进行排序,这时候,我们可能会这样写:

原始写法

packagemethodreferences;importjava.time.LocalDate;importjava.util.Arrays;importjava.util.Comparator;public classMain

{static class PersonAgeComparator implements Comparator{public intcompare(Person a, Person b) {returna.getBirthday().compareTo(b.getBirthday());

}

}public static voidmain(String[] args)

{

Person[] pArr= newPerson[]{new Person("003", LocalDate.of(2016,9,1)),new Person("001", LocalDate.of(2016,2,1)),new Person("002", LocalDate.of(2016,3,1)),new Person("004", LocalDate.of(2016,12,1))};

Arrays.sort(pArr,newPersonAgeComparator());

System.out.println(Arrays.asList(pArr));

}

}

其中,Arrays类的sort方法定义如下:

public static void sort(T[] a, Comparator super T> c)

这里,我们首先要注意Comparator接口是一个函数式接口,因此我们可以使用Lambda表达式,而不需要定义一个实现Comparator接口的类,并创建它的实例对象,传给sort方法。

使用Lambda表达式,我们可以这样写:

改进一,使用Lambda表达式,未调用已存在的方法

packagemethodreferences;importjava.time.LocalDate;importjava.util.Arrays;public classMain

{public static voidmain(String[] args)

{

Person[] pArr= newPerson[]{new Person("003", LocalDate.of(2016,9,1)),new Person("001", LocalDate.of(2016,2,1)),new Person("002", LocalDate.of(2016,3,1)),new Person("004", LocalDate.of(2016,12,1))};

Arrays.sort(pArr, (Person a, Person b)->{returna.getBirthday().compareTo(b.getBirthday());

});

System.out.println(Arrays.asList(pArr));

}

}

然而,在以上代码中,关于两个人生日的比较方法在Person类中已经定义了,因此,我们可以直接使用已存在的Person.compareByAge方法。

改进二,使用Lambda表达式,调用已存在的方法

packagemethodreferences;importjava.time.LocalDate;importjava.util.Arrays;public classMain

{public static voidmain(String[] args)

{

Person[] pArr= newPerson[]{new Person("003", LocalDate.of(2016,9,1)),new Person("001", LocalDate.of(2016,2,1)),new Person("002", LocalDate.of(2016,3,1)),new Person("004", LocalDate.of(2016,12,1))};

Arrays.sort(pArr, (a, b)->Person.compareByAge(a, b));

System.out.println(Arrays.asList(pArr));

}

}

因为这个Lambda表达式调用了一个已存在的方法,因此,我们可以直接使用方法引用来替代这个Lambda表达式,

改进三,使用方法引用

packagemethodreferences;importjava.time.LocalDate;importjava.util.Arrays;public classMain

{public static voidmain(String[] args)

{

Person[] pArr= newPerson[]{new Person("003", LocalDate.of(2016,9,1)),new Person("001", LocalDate.of(2016,2,1)),new Person("002", LocalDate.of(2016,3,1)),new Person("004", LocalDate.of(2016,12,1))};

Arrays.sort(pArr, Person::compareByAge);

System.out.println(Arrays.asList(pArr));

}

}

在以上代码中,方法引用Person::compareByAge在语义上与Lambda表达式 (a, b) -> Person.compareByAge(a, b) 是等同的,都有如下特性:

真实的参数是拷贝自Comparator.compare方法,即(Person, Person);

表达式体调用Person.compareByAge方法;

四种方法引用类型

静态方法引用

我们前面举的例子Person::compareByAge就是一个静态方法引用。

特定实例对象的方法引用

如下示例,引用的方法是myComparisonProvider对象的compareByName方法;

classComparisonProvider

{public intcompareByName(Person a, Person b)

{returna.getName().compareTo(b.getName());

}public intcompareByAge(Person a, Person b)

{returna.getBirthday().compareTo(b.getBirthday());

}

}

ComparisonProvider myComparisonProvider= newComparisonProvider();

Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);

任意对象(属于同一个类)的实例方法引用

如下示例,这里引用的是字符串数组中任意一个对象的compareToIgnoreCase方法。

String[] stringArray = {"Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda"};

Arrays.sort(stringArray, String::compareToIgnoreCase);

构造方法引用

如下示例,这里使用了关键字new,创建了一个包含Person元素的集合。

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

transferElements方法的定义如下,功能为集合拷贝,

public static , DEST extends Collection>DEST transferElements(

SOURCE sourceCollection,

SuppliercollectionFactory) {

DEST result=collectionFactory.get();for(T t : sourceCollection) {

result.add(t);

}returnresult;

}

什么场景适合使用方法引用

当一个Lambda表达式调用了一个已存在的方法

什么场景不适合使用方法引用

当我们需要往引用的方法传其它参数的时候,不适合,如下示例:

IsReferable demo = () -> ReferenceDemo.commonMethod("Argument in method.");

参考资料

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值