欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

原文地址

相关标签: Java8新特征