方法引用

发布时间 2023-04-02 15:51:34作者: wdadwa

方法引用概述

方法引用就是把已有的方法拿过来用,当作函数式接口中的抽象方法的方法体。

举例:

image

image

方法引用的使用需要满足以下四个条件:

  1. 引用处必须是函数式接口
  2. 被引用的方法必须已经存在
  3. 被引用的方法的形参和返回值需要和抽象方法保持一致
  4. 被引用方法的功能要满足当前需求

举例:

import java.util.Arrays;
public class main {
    public static void main(String[] args) {
        Integer[] arr={3,5,4,1,6,2};
        Arrays.sort(arr,main::subtraction);//方法引用,表示引用main类中的subtraction方法
        Arrays.stream(arr).forEach(s-> System.out.println(s));
    }
    public static int subtraction(int num1,int num2){
        return num2-num1;
    }
}

引用静态方法

格式:类名::静态方法名

import java.util.Arrays;
public class Text {
    public static void main(String[] args) {
        String[] arr={"3","5","4","1","6","2"};
        Arrays.stream(arr).forEach(Integer::parseInt);
    }
}

引用成员方法

引用成员方法根据引用的类的类型不同分为以下三种:

  1. 其他类:其他类对象名::方法名
  2. 本类:this::方法名
  3. 父类:super::方法名

需要注意的是这三种引用不能引用静态方法

引用构造方法

格式:类名::new

举例:Student::new

引用构造方法的时候,要保证构造方法的对象和抽象方法的返回值保持一致。

举例:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class Text {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"张无忌,15","周正若,14","赵敏,13","张强,100","张三丰,24");
        List<Student> lists = list.stream().map(new Function<String, Student>() {
            @Override
            public Student apply(String s) {//这里的形参为String s,但Student中没有这个形参的返回值,故需要手动加一个
                String[] arr = s.split(",");
                String name = arr[0];
                int age = Integer.parseInt(arr[1]);
                return new Student(age, name);
            }
        }).collect(Collectors.toList());
        
        List<Student> lists = list.stream()
            .map(Student::new)//简写好的,就是使用自己写的构造方法创建Student对象并返回给map
            .collect(Collectors.toList());
        System.out.println(lists);
    }
}
//Student类,没写get,set方法,重点看看构造方法!
public class Student {
    private int age;
    private String name;
    public Student() {
    }
    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }
    public Student(String s){//这个部分就是我们调用的
        String[] arr = s.split(",");
        this.name = arr[0];
        this.age = Integer.parseInt(arr[1]);//这里不需要返回值,因为构造方法被调用后会创建对象的
    }

}

其他调用方式

使用类名引用成员方法

格式:类名::成员方法

举例:String::substring

import java.util.ArrayList;
import java.util.Collections;
public class Text {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"aaa","bbb","ccc","ddd");
        //详细写
        list.stream().map(new Function<String, String>() {
            @Override
            public String apply(String s) {//这里的第一个参数决定了在使用类名引用方法中只能使用哪个类的方法。
                //这里是String类,故只能使用String类的方法。
                return s.toUpperCase();
            }
        }).forEach(s-> System.out.println(s));    
        //简写
        list.stream()
            .map(String::toUpperCase)
            .forEach(s-> System.out.println(s));
    }
}

使用类名引用成员方法和使用对象名字引用成员方法要遵循的规则不一样。

使用类名引用成员方法的规则:

  1. 需要有函数式接口
  2. 被引用的方法必须已经存在
  3. 被引用方法的形参,需要根抽象方法的第二个形参到最后一个形参保持一致,返回值也要保持一致
  4. 被引用方法的功能需要满足当前需求。

抽象方法形参详解:

第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法。

在Stream流中,第一个参数一般都表示流中每一个数据,假设流中数据是字符串,那么使用这种方式引用,只能引用String类中方法。

第二个参数到最后一个参数:跟被引用方法的形参保持一致。

如果没有第二个参数,说明被引用的方法需要是无参成员方法。

局限性:

  • 不能引用所有类中的成员方法
  • 是跟抽象方法的第一个参数有关,这个参数是什么类型,那么就只能使用这个类的方法。

引用数组的构造方法

格式:数据类型[]::new

举例int[]::new

练习:集合中存储一些整数,收集到数组中

import java.util.ArrayList;
import java.util.Collections;
import java.util.function.IntFunction;
public class Text {
    public static void main(String[] args) {
        ArrayList<Integer> list=new ArrayList<>();
        Collections.addAll(list,1,2,3,4,5,6,7);
        //原本的写法
        Integer[] i=list.stream().toArray(new IntFunction<Integer[]>() {
            @Override
            public Integer[] apply(int value) {
                return new Integer[value];
            }
        });
        //新写法
        Integer[] i1=list.stream().toArray(Integer[]::new);
        //数组的类型需要跟流中数据的类型保持一致
    }
}