Java学习笔记-方法引用

方法引用(Method Reference)

上一篇中记录了Lambda表达式,其可以创建匿名方法。当Lambda表达式只是调用一个存在的方法时,可以采用方法引用(JDK8具有的特性)。如下:

 1 public class Person {
 2
 3     public enum Sex {
 4         MALE, FEMALE
 5     }
 6
 7     String name;
 8     LocalDate birthday;
 9     Sex gender;
10     String emailAddress;
11     int age;
12
13     public int getAge() {
14         return age;
15     }
16
17     public LocalDate getBirthday() {
18         return birthday;
19     }
20
21     public static int compareByAge(Person a, Person b) {
22         return a.birthday.compareTo(b.birthday);
23     }
24 } 

假设需要对一组人员按年龄进行排序,可以采用下边的方式,将人员数组与实现的比较器,传递给Array.sort方法:

1 Person[] rosterAsArray = roster.toArray(new Person[roster.size()]);
2
3 class PersonAgeComparator implements Comparator<Person> {
4     public int compare(Person a, Person b) {
5         return a.getBirthday().compareTo(b.getBirthday());
6     }
7 }
8
9 Arrays.sort(rosterAsArray, new PersonAgeComparator()); 

当然,可以将PersonAgeComparator的实现采用Lambda表达式,如下:

1  Arrays.sort(rosterAsArray, (a,b) -> a.birthday.compareTo(b.birthday)); 

Person类中已经包含根据年龄的比较compareByAge,只需要在Lambda表达式体中直接调用即可

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

由于Lambda表达式调用一个已经存在的方法,可以使用方法引用代替Lambda表达式,如下:

1 Arrays.sort(rosterAsArray, Person::compareByAge); 

其中 ,Person::compareByAge 与 (a, b) -> Person.compareByAge(a, b)是等价的。(1)其参数拷贝于Comparator<Person>.compare,即 (Person, Person);(2)body将调用Person.compareByAge。

方法引用类别

有4种方法引用,如下:

  • 引用静态方法,如 ContainingClass::staticMethodName;
  • 引用实例方法,如 containingObject::instanceMethodName;
  • 引用特殊类型对象的方法,如 ContainingType::methodName;
  • 引用构造函数,如 ClassName::new。

(1)引用静态方法

上文中的例子即为静态方法引用。

(2)引用实例方法

即通过类的实例引用方法,如下:

 1 class ComparisonProvider {
 2     public int compareByName(Person a, Person b) {
 3         return a.getName().compareTo(b.getName());
 4     }
 5
 6     public int compareByAge(Person a, Person b) {
 7         return a.getBirthday().compareTo(b.getBirthday());
 8     }
 9 }
10 ComparisonProvider myComparisonProvider = new ComparisonProvider();
11 Arrays.sort(rosterAsArray, myComparisonProvider::compareByName); 

(3)引用特殊类型对象的方法

以String为例:

1 String[] stringArray = { "Barbara", "James", "Mary", "John",
2     "Patricia", "Robert", "Michael", "Linda" };
3 Arrays.sort(stringArray, String::compareToIgnoreCase); 

(4)引用构造函数

假设transferElements实现从一个集合到另一个集合拷贝元素,如下:

 1 public static <T, SOURCE extends Collection<T>, DEST extends Collection<T>>
 2     DEST transferElements(
 3         SOURCE sourceCollection,
 4         Supplier<DEST> collectionFactory) {
 5
 6         DEST result = collectionFactory.get();
 7         for (T t : sourceCollection) {
 8             result.add(t);
 9         }
10         return result;
11 } 

其中Supplier包含一个get方法,只返回一个空的集合对象,并且不需要任何参数,可以使用Lambda表达式实现,如下:

1 Set<Person> rosterSetLambda =
2     transferElements(roster, () -> { return new HashSet<>(); }); 

此时可以采用引用构造函数的方法,如下:

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

总结

  • 对于Lambda表达式,当只是调用一个已存在的方法时,可以采用方法引用的方式实现,编译器会自行翻译

参考

Method references

原文地址:https://www.cnblogs.com/shuimuzhushui/p/8261205.html

时间: 2024-11-06 19:45:30

Java学习笔记-方法引用的相关文章

Java学习笔记-方法总结

1.程序模块化和可重用性是软件工程的中心目标之一.Java提供了很多有助于完成这一目标的有效结构.方法就是一个这样的结构.2.方法头指定方法的修饰符,返回值类型,方法名和参数.3.方法可以返回一个值.返回值类型是方法要返回的值的数据类型.如果方法不返回值,则返回值类型就是关键字void.4.参数列表是指方法中参数的类型,次序和数量.方法名和参数列表一起构成方法签名.参数是可选的,也就是说,一个方法可以不包含参数.5.return语句也可以用在void方法中,用来终止方法并返回到方法的调用者.在方

java学习笔记 --- 方法

一.方法  (1)方法:就是完成特定功能的代码块.   注意:在很多语言里面有函数的定义,而在Java中,函数被称为方法.  (2)格式:   修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2...) {    方法体语句;     return 返回值;   }  修饰符:目前就用 public static.   返回值类型:就是功能结果的数据类型    方法名:就是起了一个名字,方便我们调用该方法.   参数类型:就是参数的数据类型   参数名:就是变量 参数分类:  

Java学习笔记之方法重载,动态方法调度和抽象类

一.方法重载 如果子类中的方法与它的超类中的方法有相同的方法名,则称子类中的方法重载超类中的方法,特别是当超类和子类中的方法名和参数类型都相同时,在子类中调用该方法时,超类中的方法会被隐藏.考虑下面程序: 1 class A 2 { 3 int i, j; 4 A(int a, int b) 5 { 6 i = a; 7 j = b; 8 } 9 10 // display i and j 11 void show() 12 { 13 System.out.println("i and j: &

Java学习笔记之深入理解引用

引言:Java中数据传递的方式,除了基本数据类型是按照值传递,其它类型全部是按照引用传递,这和C++有很大区别,但是很多网上文章都解释的不清楚,甚至是错误的,在查阅资料之后,下面整理出一个比较容易理解的版本. 我们知道引用根据引用的类型不同有许多名称,如字符串引用,数组引用等等. 一.栈内存和堆内存 我们数组来引出和解释这两个概念. 数组引用变量只是一个引用,这个引用可以指向任何有效的内存. 简单的理解就是,这个引用是用来存放数据地址的(数据地址指向数据在内存中的存储位置),在声明引用变量的时候

Java学习笔记_25_Collections类

25.Collections类: Collections类是一个工具类,用来对集合进行操作,它主要是提供一些排序算法,包括随机排序.反相排序等. Collections类提供了一些静态方法,实现了基于List容器的一些常用算法. Collections的一些方法列表: · void sort(List): 对List内的元素进行排序. · void shuffle(List): 对List内的元素随机排序. · void reverse(List): 对List内的元素进行逆序排列. · voi

java学习笔记3——java关键字

java学习笔记3——java关键字 虽然老师说不用刻意的去记忆,但是我还是在网上找到了非常详细的注解,再次收藏 关键字的类型表: 各个关键字的详细注解和实例,按首字母排序: 1.abstract abstract 关键字可以修改类或方法. abstract 类可以扩展(增加子类),但不能直接实例化. abstract 方法不在声明它的类中实现,但必须在某个子类中重写. -示例- public abstract class MyClass{ } public abstract String my

【Java学习笔记之二十六】深入理解Java匿名内部类

在[Java学习笔记之二十五]初步认知Java内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意的事项.如何初始化匿名内部类.匿名内部类使用的形参为何要为final. 一.使用匿名内部类内部类 匿名内部类由于没有名字,所以它的创建方式有点儿奇怪.创建格式如下: new 父类构造器(参数列表)|实现接口() { //匿名内部类的类体部分 } 在这里我们看到使用匿名内部类我们必须要继承一个父类或者

Java学习笔记之继承

一.继承的基础 在Java术语中,被继承的类叫超类(superclass),继承超类的类叫子类(subclass). 举例说明: 1 class Box 2 { 3 public double width; 4 public double height; 5 public double depth; 6 7 //重载构造方法 8 public Box(Box ob) 9 { 10 width = ob.width; 11 height = ob.height; 12 depth = ob.dep

Java 学习笔记(2015.7.13~17)

Java 学习笔记(2015.7.13~17) Java this关键字 表示本类中的属性,调用本类中的方法 class Person {        private String name;         private int age;         public Person(String name, int age) {         this.name = name;//调用本类中的属性         this.age = age;//同上} //get&set方法: