Java8方法引用,示例讲解
目录
看过了Lambda表达式和函数式接口编程,再来看下方法引用。
方法引用理解起来有点恶心,多花点时间,多写就好了。
1、四种不同方式的引用
- 方法引用通过方法的名字来指向一个方法。
- 方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
- 方法引用使用一对冒号 :: 。
下面,我们在 Car 类中定义了 4 个方法作为例子来区分 Java 中 4 种不同方法的引用。
@FunctionalInterface
public interface Supplier<T> {
T get();
}
class Car {
//Supplier是jdk1.8的接口,这里和lamda一起使用了
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());
}
}
构造器引用:它的语法是Class::new,或者更一般的Class< T >::new实例如下:
final Car car = Car.create( Car::new );
final List< Car > cars = Arrays.asList( car );
静态方法引用:它的语法是Class::static_method,实例如下:
cars.forEach( Car::collide );
特定类的任意对象的方法引用:它的语法是Class::method实例如下:
cars.forEach( Car::repair );
特定对象的方法引用:它的语法是instance::method实例如下:
final Car police = Car.create( Car::new );
cars.forEach( police::follow );
2、方法引用示例
public class Java8Tester {
public static void main(String args[]){
List<String> names = new ArrayList();
names.add("Google");
names.add("Runoob");
names.add("Taobao");
names.add("Baidu");
names.add("Sina");
names.forEach(System.out::println);
}
}
实例中我们将 System.out::println 方法作为静态方法来引用。
输出结果:
Google
Runoob
Taobao
Baidu
Sina
3、使用场景示例
看了上面的语法,可能还是有点懵,那到底什么时候使用方法引用呢?
请看下面的示例:
class Test06 {
public static void main(String[] args) {
// 1.对象::实例方法名
Consumer<String> con1 = x -> System.out.println(x);
con1.accept("买裤子");
/*
Consumer:的 accept 方法:void accept(T t);
方法体中的方法: public void println(String x)
如果满足: 前面的函数式接口的 参数 和 返回值
和
方法体中的方法的 参数 和 返回值 一致,那么可以使用方法引用。
*/
Consumer<String> con2 = System.out::println;
con2.accept("买裤子");
// 2. 类::静态方法名
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
System.out.println(com.compare(10, 20));
/*
Comparator的compare方法:int compare(T o1, T o2);
方法体中的方法:int compare(T o1, T o2);
两者一致,可以使用方法应用。
*/
Comparator<Integer> com2 = Integer::compare;
System.out.println(com2.compare(10, 20));
// 类::实例方法名
BiPredicate<String, String> bp = (x, y) -> x.equals(y);
System.out.println(bp.test("abc", "abc"));
/*
boolean test(T t, U u);
public boolean equals(Object anObject)
前提:一个作为方法的调用者,一个作为方法的实际参数,才能用这种写法。
*/
BiPredicate<String, String> bp2 = String::equals;
System.out.println(bp.test("abc", "abc"));
}
个人理解:
- 方法引用语法也是建立在函数式接口的基础上的;
- 通俗点讲,方法引用就是,在使用函数式接口的时候,我们可以通过方法引用的方式来指明我们真正调用的是哪个类的哪个方法,例如上面实例中的【Comparator com2 = Integer::compare;System.out.println(com2.compare(10, 20));】
表示的意思,就是“我们要比较10和20的大小,使用了函数式接口Comparator的compare(T o1, T o2)方法,但实现类是Integer的compare方法”。
Comparator的compare源码:
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
Integer的compare方法源码:
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
4、IDEA小技巧
通过IDEA编辑器,会提示你用方法引用来代替你写的代码【快捷键Alt+Enter】。如下图:如果是Lambda写法,左边会显示一个对应的Lambda符号,你可以选择用方法引用来代替Lambda表达式。
如果没有看到Lambda符号,可以按下列步骤配置:
-
右侧栏,鼠标右击,选择“Configure Gutter Icons...”
-
勾选Lmbda -> Apply
“人生当中成功只是一时的,失败却是主旋律,但是如何面对失败,却把人分成了不同的样子。有的人会被失败击垮,有的人能够不断地爬起来继续向前。真正的成熟,应该并不是追求完美,而是直面自己的缺憾。这,才是生活的本质”
公众号:Java尖子生
[关注公众号免费领取Java学习、面试资料。]
上一篇: 用Matlab进行时域信号的频谱分析
下一篇: 多项式乘法与FFT——学习笔记