Java 8新特征 方法引用
程序员文章站
2022-06-07 19:49:49
...
一、是什么?
方法引用是用来直接访问类或者实例已经存在的方法或者构造方法。
二、哪里能用?
当Lambda表达式中只是执行一个方法调用时。
三、怎么理解?
这里以Arrays的sort方法进行讲解:public static void sort(T[] a, Comparator<? super T> c)
public void introduce() {
String[] strArray ={“a”, “c”, “b”};
//在学完lambda表达式后,如果你想创建一个Comparator实例,你可能会用以下方法:
Arrays.sort(strArray, (s1,s2)->s1.compareTo(s2));
//你仔细看就会发现整个lambda体其实就只是在调用String类的compareTo()方法而已
//因此我们可以使用方法引用的方式来进行简写
Arrays.sort(strArray,String::compareTo);
}
四、有哪些?
方法引用 ,形式有三种: 1、实例::实例方法名 2、 类名::静态方法名 3、类名::实例方法名
构造器引用 ,形式有一种: 类名::new
数组引用 ,形式有一种:类型[]::new
五、具体例子
准备:定义一个person类,字段如下:
public class Person {
private String name;
private int age;
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//省略get/set方法...
}
1. 实例::实例方法名
public void test1(){
Person person=new Person("小明",18);
Supplier<String> supplier=()->person.getName();
System.out.println(supplier.get());
//上面lambda体只用到person实例的getName()方法,因此可以改写成实例::实例方法名
Supplier<String> supplier1=person::getName;
System.out.println(supplier1.get());
}
2. 类名::静态方法名
public void test2(){
//普通lambda方式
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
//类名:静态方法名
Comparator<Integer> com2 = Integer::compare;
}
3. 类名::实例方法名,前提:Lambda 参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数。
public void test3() {
String[] strArray = {"a", "c", "b"};
Arrays.sort(strArray, (s1, s2) -> s1.compareTo(s2));
//lambda的第一个参数s1 是实例方法compareTo()的调用者
//且lambda的第二个参数s2 是compareTo()的参数
Arrays.sort(strArray, String::compareTo);
}
4. 类名::new ,前提:构造器的参数列表,需要与函数式接口中参数列表保持一致
public void test4(){
// Function的参数为String,匹配 public Person(String name)
Function<String, Person> fun = Person::new;
//BiFunction的参数为String,Integer,匹配 public Person(String name, int age)
BiFunction<String, Integer, Person> fun2 = Person::new;
}
5. 类型[]::new
public void test5() {
Function<Integer, String[]> fun = (length) -> new String[length];
String[] strs1 = fun.apply(10);
System.out.println(strs1.length);
System.out.println("--------------------------");
Function<Integer, String[]> fun2 = String[]::new;
String[] strs2 = fun2.apply(20);
System.out.println(strs2.length);
}
6. 补充:
6.1. 当lambda体调用的方法是父类中的方法或者是当前类中的方法时,可以使用 super::实例方法名 或 this::实例方法名
public class Father {
public int add(int a, int b) {
return a + b;
}
}
public class Son extends Father {
public int add(int a, int b) {
return a + b + 2;
}
public int calculate(BiFunction<Integer, Integer, Integer> function, int a, int b) {
return function.apply(a, b);
}
@Test
public void test() {
int fatherAdd = calculate(super::add, 1, 2);
int sonAdd = calculate(this::add, 1, 2);
System.out.println(fatherAdd);
System.out.println(sonAdd);
}
}
//运行结果:
3
5
6.2 当lambda体中的方法有泛型是,可以在双冒号:: 之后指定类型。
public interface MyFunc<T> {
int func(T[] als, T v);
}
public class MyArrayOps {
//统计v在数组中出现的次数
public static <T> int countMatching(T[] array, T v) {
int count = 0;
for (T t : array) {
if (t.equals(v)) count++;
}
return count;
}
}
public class Run {
public static <T> int myOp(MyFunc<T> f, T[] array, T v) {
return f.func(array, v);
}
public static void main(String[] args) {
Integer[] vals = {1, 2, 3, 4, 2, 3, 4, 4, 5};
String[] strs = {"One", "Two", "Three", "Two"};
//不指定MyFunc类型时,可根据后面的参数推断
int count1 = myOp(MyArrayOps::countMatching, vals, 4);
System.out.println("vals contains " + count1 + " 4s");
//要指定类型时,可以在::后面指定,指定完可以限制后面两个参数的类型
int count2 = myOp(MyArrayOps::<String>countMatching, strs, "Two");
System.out.println("strs contains " + count2 + " Twos");
}
}
//本例子参考自:https://www.cnblogs.com/xiaoxi/p/7099667.html
原文地址
上一篇: Stream流API
下一篇: PHP开发注意事项总结_PHP
推荐阅读
-
Java8新特性(三)集合之 Stream 流式操作
-
JAVA 8 新特性Stream初体验
-
聊聊 Java8 以后各个版本的新特性
-
Java日期时间API系列12-----Jdk8中java.time包中的新的日期时间API类,日期格式化,常用日期格式大全
-
Java8新特性Stream的完全使用指南
-
Java日期时间API系列8-----Jdk8中java.time包中的新的日期时间API类的LocalDate源码分析
-
Java8新特性Lambda表达式的一些复杂用法总结
-
函数式接口 + Lamda表达式推导过程(Java8 新特性)
-
Java 8中default方法能做什么?不能做什么?
-
【java新特性】之方法引用与Lambda表达式