Java 引用

89 阅读3分钟

方法引用

  • 把已经有的方法拿过来用,当作函数式接口中抽象方法的方法体
  • 使用条件
    • 引用处必须是函数式接口
    • 被引用的方法必须已经存在
    • 被引用方法的形参和返回值需要跟抽象方法保持一致
    • 被引用方法的功能要满足当前需求
Arrays.sort(arr, new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2 - o1;  
    }
});

//这个类叫做FunctionDemo1
Arrays.sort(arr, FunctionDemo1::subtraction);

//可以是Java已经写好的,也可以是一些第三方工具类
public static int subtraction(int num1, int num2) {
    return num2 - num1;
}

引用静态方法

  • 格式
    • 类名::静态方法
  • 范例
    • Integer::parseInt

引用成员方法

  • 格式
    • 对象::成员方法
    • 其他类:其他类对象::方法名
      • 注意:是其他类的对象:new StringOperation()::stringJudge
    • 本类:this::方法名
      • 如果引用处是静态方法,在静态方法中是没有this的,所以想要在静态方法中引用本类的方法,只能先new一个本类的对象:new FunctionDemo3()::stringJudge
    • 父类:super::方法名
      • 同上

引用构造方法

  • 格式
    • 类名::new
  • 范例
    • Student::new
  • Stream流中 collect(Collector collector) 终结方法中的collect(Collectors.toList()) 中的toList方法底层原理
    • 在底层其实就是通过方法引用创建ArrayList对象和引用LIst中的add方法将每个元素添加到ArrayList中
public static <T> Collector<T, ?, List<T>> toList() {
    return new CollectorImpl<>(ArrayList::new, List::add, (left, right) -> { left.addAll(right); return left;}, CH_ID);
}

使用类名引用成员方法

  • 独有的规则

    • 需要有函数式接口
    • 被引用的方法必须存在
    • 被引用方法的形参,需要跟抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致
    • 被引用的方法的功能需要满足当前需求
  • 抽象方法形参的详解

    • 第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法
      • 在Stream流当中,第一个参数一般都表示流里面的每一个数据
      • 假设流里面的数据都是字符串,那么使用这种方式进行方法引用,只能引用String这个类中的方法
    • 第二个参数到最后一个参数:跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用的方法需要时无参的成员方法
  • 格式

    • 类名::成员方法
  • 范例

    • String::substring
  • 局限性

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

引用数组的构造方法

  • 格式
    • 数据类型[]::new
  • 范例
    • int[]::new

练习

  • 集合中存储一些字符串的数据,比如"张三,23",收集到Student类型的数组中,使用方法引用完成
  • 创建集合添加学生对象,学生对象属性:name,age,只获取姓名并放到数组,中使用方法引用完成
  • 创建集合添加学生对象,学生对象属性:name,age,把姓名年龄拼接成,"张三-23"的字符串,并放到数组当中,使用方法引用完成
//标准javabean
public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String s) {
        this.name = s.split(",")[0];
        this.age = Integer.parseInt(s.split(",")[1]);
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return this.name + "-" + this.age;
    }
}
//test1
public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();
    Collections.addAll(list, "张三,23", "李四,24", "王五,25");

    Student[] arr = list.stream()
            .map(Student::new)
            .toArray(Student[]::new);

    for (Student student : arr) {
        System.out.println(student);
    }
}
//test2
public static void main(String[] args) {
    Student s1 = new Student("张三", 23);
    Student s2 = new Student("李四", 24);
    Student s3 = new Student("王五", 25);

    ArrayList<Student> list = new ArrayList<>();
    Collections.addAll(list, s1, s2, s3);

    String[] arr = list.stream()
            .map(Student::getName)
            .toArray(String[]::new);

    for (String s : arr) {
        System.out.println(s);
    }
}
//test3
public static void main(String[] args) {
    Student s1 = new Student("张三", 23);
    Student s2 = new Student("李四", 24);
    Student s3 = new Student("王五", 25);

    ArrayList<Student> list = new ArrayList<>();
    Collections.addAll(list, s1, s2, s3);

    String[] arr = list.stream()
            .map(Student::toString)
            .toArray(String[]::new);

    for (String s : arr) {
        System.out.println(s);
    }
}