方法引用是什么?
w3c教程上这样解释:方法引用通过方法的名字来指向一个方法。反正这句话我是看不明白啥意思,结合下面的要介绍的例子我认为这样解释更通俗易懂(了解方法引用前,建议先了解下Lambda表达式,请戳:Lambda表达式):方法引用就是一个特殊的Lambda表达式,如果某个方法和Lambda表达式的内容一样,那么就可以将这个Lambda替换成方法引用的形式。
方法引用的四种形式:
- 构造器引用:它的语法是Class::new,或者更一般的Class< T >::new
- 静态方法引用:语法是Class::static_method
- 特定类的任意实例的方法引用:它的语法是Class::method
特定实例的方法引用:它的语法是instance::method
下面详细介绍四种形式,先引入例子:
class Car {
//创建车
public static Car create(final Supplier<Car> supplier) {
return supplier.get();
}
//撞车
public static void collide(final Car car) {
System.out.println("Collided " + car.toString());
}
//跟车
public void follow(final Car another) {
System.out.println("Following the " + another.toString());
}
//修车
public void repair() {
System.out.println("Repaired " + this.toString());
}
}
- 构造器引用
final Car car = Car.create( Car::new );
我们看下使用Lambda表达式的写法:
final Car car = Car.create( ()->new Car());
再看下在JAVA7中的写法:
final Car car = Car.create(new Supplier<Car>() {
@Override
public Car get() {
return new Car();
}
});
这样是不是明白了呢,工厂方法create需要一个匿名内部类作为参数,里面的get()方法每次调用产生一个实例,Lambda表达式就是这个匿名内部类的简写形式,而构造器引用则是Lambda表达式的简写形式。
- 静态方法引用
此处介绍使用了JAVA8中集合的forEach,不了解的请戳:JAVA8集合遍历之forEach
//先创建一个集合
final List< Car > cars = Arrays.asList( car );
cars.forEach( Car::collide );
我们看下Lambda写法:
cars.forEach((o)->Car.collide(o));
再看下java7中的写法:
for (Car o : cars) {
Car.collide(o);
}
在JAVA7中遍历cars并将其中的对象传递给静态方法collide,JAVA8中的集合遍历forEach隐含了一个car对象,所以Lambda中也是使用了一个参数,静态方法引用所对应的方法collide也是只有一个car对象,也就是说,静态方法引用的使用必须保证和其引用的静态方法的参数个数一致。
- 特定类的任意实例的方法引用
cars.forEach( Car::repair );
Lambda写法:
cars.forEach((o)->o.repair());
JAVA7中写法:
for (Car o : cars) {
o.repair();
}
通过JAVA7的写法能看到特定类的任意实例的方法引用的解释:使用的是Car类的实例o的repair方法的引用。
- 特定实例的方法引用
//创建个实例
final Car police = Car.create( Car::new );
cars.forEach( police::follow );
Lambda写法:
cars.forEach((o)->police.follow(o));
JAVA7中写法:
for (Car o : cars) {
police.follow(o);
}
通过JAVA7的写法也能看到对 特定实例的方法引用的解释:使用的是一直是Car类的police实例的方法follow。
后两种方法引用开始实在有点难以理解,但是通过结合JAVA7中的写法,很容易就想明白了。
总结(使用场景):
构造器引用:是对匿名内部类的使用的一种简写形式。
静态方法引用:就是对静态方法的引用简写形式。
特定类的任意实例的方法引用:就是使用指定类的任意一个实例的方法的简写形式。
特定实例的方法引用:就是使用指定类的指定实例的方法的简写形式。