一、什么是方法引用
方法引用是java8的新特性之一,它使得编写代码的时候可以通过方法名直接引用一个已经存在的方法,这样可以使代码简洁紧凑,避免重复编码。
方法引用使用两个冒号(::)表示,比如下面代码:
Stream.of(1,2,3,4).forEach(System.out::println);
下面再举一个例子,让大家先来体验一下方法引用带来的方便。
public static void main(String argv[]){
//使用匿名类完成加和操作
System.out.println(Stream.of(1,2,3,4).reduce(new BinaryOperator<Integer>(){
@Override
public Integer apply(Integer a,Integer b){
return a+b;
}
}));
//使用lambda表达式完成加和操作
System.out.println(Stream.of(1,2,3,4).reduce((x,y)->(x+y)));
//使用方法引用完成加和操作
System.out.println(Stream.of(1,2,3,4).reduce(Integer::sum));
}
可以看到,方法引用不仅使代码变得简洁,而且可读性更高。
方法在被引用的时候不会执行该方法。方法引用也是一个lambda表达式。
二、方法引用有哪些类型
方法引用主要分为以下四类:
- 引用静态方法;
- 引用构造方法;
- 引用实例方法;
- 引用某个类的任意实例方法。
下面通过例子详细介绍一下如何使用这些类型。
1、引用静态方法
这个是最简单的,也是最容易理解的,语法是:类名::静态方法名。
下面举几个例子:
public static class StringComparator{
public static int compare(String a,String b){
return a.compareTo(b);
}
}
public static void main(String argv[]){
//使用方法引用完成排序
List<String> list=Arrays.asList("Allen","Brook","Olivia","Alice","Isabella");
list.sort(StringComparator::compare);
list.forEach(System.out::println);
//使用方法引用完成加和
System.out.print(Arrays.asList(1,2,3,4,5).stream().reduce(Integer::sum));
}
运行结果:
Alice
Allen
Brook
Isabella
Olivia
Optional[15]
2、引用构造方法
构造方法引用的语法是类名::new,也就是在双冒号后面加一个new关键字即可,这相当于使用new 类名()的方式。
下面代码使用Integer::new将流里面的每个元素转换为Integer类型。
Stream.of("1","2","3").map(Integer::new).forEach(System.out::println);
除了上面这种形式的引用外,还有一种是数组的构造方法引用,语法为类名[]::new。代码如下:
public static void main(String argv[]){
//创建一个int数组
Function<Integer,int[]> s=int[]::new;
int[] array=s.apply(10);
array[0]=1;
}
3、引用实例方法
实例方法引用指的是引用一个指定对象的方法,语法为对象::方法名。像本文一开始介绍的System.out::println就是实例方法引用。
下面再看一下例子:
public static class StringComparator{
public int compare(String a,String b){
return a.compareTo(b);
}
}
public static void main(String argv[]){
List<String> list=Arrays.asList("Allen","Brook","Olivia","Alice","Isabella");
StringComparator comparator=new StringComparator();
//引用StringComparator对象的方法
list.sort(comparator::compare);
System.out.println(list);
}
this和super关键字也可以在方法引用中使用,this表示当前实例,super表示父类对象,引用本实例方法可以是this::方法名,引用父类方法是super::方法名。
public static class Human{
public String sayHello(String name){
return "hello i am "+name;
}
}
public static class Man extends Human{
String name;
public void setName(String name){
Function<String,String> f=super::sayHello;
System.out.println(f.apply(name));
}
public String getName(){
return name;
}
public void checkIsHaveName(){
Supplier<String> f=this::getName;
System.out.println(f.get()==null);
}
}
public static void main(String argv[]){
Man man=new Man();
man.checkIsHaveName();
man.setName("Brook");
}
4、引用某个类的任意实例方法
这个类型的语法是类名::实例方法名
。这要求所有的实例必须是同一个类的对象。
public static void main(String argv[]){
List<String> list=Arrays.asList("Allen","Brook","Olivia","Alice","Isabella");
list.sort(String::compareTo);
System.out.println(list);
}
上面的代码运行过程中,会调用每个String对象的compareTo()方法。