30-方法引用

方法引用

1、概述
  • 就是把已有的方法拿过来用,当做函数式接口中抽象方法的方法体

  • 像之前这样写排序

    在这里插入图片描述

  • Lambda表达式都不是最简洁的

    Arrays.sort(arr, (o1, o2) -> o2 - o1);
    
  • 比如现在已经有一个写好的subtraction方法,在比较规则这里可以直接引用subtraction方法

    在这里插入图片描述



2、注意事项
  • 也不是什么方法都可以被引用的,必须满足以下要求

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

    在这里插入图片描述


    在这里插入图片描述

  • 要求2:被引用的方法必须是已经存在的

    在这里插入图片描述

  • 要求3:被引用方法的形参和返回值需要跟抽象方法保持一致

    在这里插入图片描述

  • 要求4:被引用方法的功能要满足当前需求

    在这里插入图片描述


3、例子
package com.app.demo34_method_reference_test;

import java.util.Arrays;
import java.util.Comparator;

public class Tets1 {
    public static void main(String[] args) {
        /*
            方法引用
              需求:创建一个数组,进行倒序排列
         */
        Integer[] arr = {3, 5, 1, 2, 6, 4};

        // 匿名内部类
        /*Arrays.sort(arr, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });*/

        // lambda表达式
        // 因为第二个参数的类型Comparator是一个函数式接口
        /*Arrays.sort(arr, (Integer o1, Integer o2) -> {
            return o2 - o1;
        });*/

        // lambda表达式简化格式
//        Arrays.sort(arr, (o1, o2) -> o2 - o1);

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

        // 表示引用Test1类里面的subtraction方法
        // 把这个方法当做抽象方法的方法体
        Arrays.sort(arr, Tets1::subtraction);

        System.out.println(Arrays.toString(arr));
    }

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

Process finished with exit code 0



小结

1、什么是方法引用?

  • 把已经存在的方法拿过来用,当做函数式接口抽象方法的方法体

2、::是什么符号?

  • 方法引用符号

3、方法引用时要注意什么?

  • 引用处需要是函数式接口
  • 被引用的方法必须是已存在的
  • 被引用的方法的形参和返回值需要跟抽象方法一致
  • 被引用的方法的功能要满足当前的需求


4、分类
(1)引用静态方法
  • 格式:

    类名::静态方法
    
  • 范例:

    Integer::parseInt
    
  • 练习:

    集合中有以下数字,要求把它们都变成int类型

    “1”, “2”, “3”, “4”, “5”

    package com.app.demo34_method_reference_test;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.function.Function;
    
    public class Test2 {
        public static void main(String[] args) {
            /*
                练习(引用静态方法):
                    集合中有以下数字,要求把它们都变成int类型
                    "1", "2", "3", "4", "5"
             */
            ArrayList<String> list = new ArrayList<>();
            Collections.addAll(list, "1", "2", "3", "4", "5");
    
            // 把它们都变成int类型
            // 匿名内部类
            /*list.stream().map(new Function<String, Integer>() {
                @Override
                public Integer apply(String s) {
                    int n = Integer.parseInt(s);
                    return n;
                }
            }).forEach(s -> System.out.print(s + " "));*/
    
            // lambda表达式
            /*list.stream()
                    .map( s -> Integer.parseInt(s))
                    .forEach(s -> System.out.print(s + " "));*/
    
            // 方法引用
            list.stream().map(Integer::parseInt).forEach(s -> System.out.print(s + " "));
        }
    }
    
    1 2 3 4 5 
    Process finished with exit code 0
    
    

(2)引用成员方法
  • 格式:

    对象::成员方法
    
  • 引用其他类:

    其他类对象::成员方法
    
  • 引用本类:

    this::成员方法
    
  • 引用父类:

    super::方法名
    
  • 注意:不能在静态方法里引用本类、父类的成员方法

  • 练习1

    集合中有一些名字,按照要求过滤数据:

    名字:"张无忌","周芷若","赵敏","张强","张三丰"
    要求:只要以张开头,而且名字是3个字的
    
    package com.app.demo34_method_reference_test;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.function.Consumer;
    import java.util.function.Predicate;
    
    public class Test3 {
        public static void main(String[] args) {
            /*
               练习(引用成员方法):
                 集合中有一些名字,按照要求过滤数据:
                   名字:"张无忌","周芷若","赵敏","张强","张三丰"
                   要求:只要以张开头,而且名字是3个字的
             */
            // 1.创建集合,添加数据
            ArrayList<String> list = new ArrayList<>();
            Collections.addAll(list, "张无忌","周芷若","赵敏","张强","张三丰");
    
            // 2.只要以张开头,而且名字是3个的
            // 匿名内部类
            /*list.stream().filter(new Predicate<String>() {
                @Override
                public boolean test(String s) {
                    return s.startsWith("张") && s.length() == 3;
                }
            }).forEach(new Consumer<String>() {
                @Override
                public void accept(String s) {
                    System.out.println(s);
                }
            });*/
    
            // lambda表达式
            /*list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3)
                    .forEach(s -> System.out.println(s));*/
    
            // 引用其他类的成员方法:
            // 格式:其他类对象::成员方法
            /*list.stream().filter(new StringOperation()::stringJude)
                    .forEach(System.out::println);*/
    
            // 引用本类的成员方法:
            // 格式:this::成员方法
            // this报错原因:因为在静态方法中是没有this的
            /*list.stream().filter(this::stringJude)
                    .forEach(System.out::println);*/
            // 解决办法:直接new本类对象即可
            list.stream().filter(new Test3()::stringJude).forEach(System.out::println);
        }
    
        public boolean stringJude(String s) {
            return s.startsWith("张") && s.length() == 3;
        }
    }
    
    张无忌
    张三丰
    
    Process finished with exit code 0
    
    
  • 练习2

    GUI界面中点击事件的方法引用写法

    package com.app.demo34_method_reference_test;
    
    import javax.swing.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    /*
        界面父类
     */
    class MyJFrame extends JFrame{
        public void superMethod1(ActionEvent e) {
            System.out.println("注册按钮被点击了一下~");
        }
    }
    
    /*
        界面类
     */
    class JFrameTest extends MyJFrame{
        // 创建按钮对象
        JButton login = new JButton();
        JButton register = new JButton();
    
        public JFrameTest() {
            // 初始化界面
            initJFrame();
    
            // 给界面添加组件
            initView();
    
            this.setVisible(true);
        }
    
        public void initView() {
            login.setText("登录");
            login.setBounds(250, 150, 100, 100);
            // 引用本类的成员方法
            login.addActionListener(this::thisMethod1);
            this.getContentPane().add(login);
    
            register.setText("注册");
            register.setBounds(250, 250, 100, 100);
            // 引用父类的成员方法
            register.addActionListener(super::superMethod1);
            this.getContentPane().add(register);
        }
    
        
        public void thisMethod1(ActionEvent e) {
            System.out.println("登录按钮被点击了一下~");
        }
    
        //初始化组件,在这个界面中添加内容
        public void initJFrame() {
            this.setSize(633, 423);//设置宽高
            this.setTitle("界面 V1.0");//设置标题
            this.setDefaultCloseOperation(3);//设置关闭模式
            this.setLocationRelativeTo(null);//居中
            this.setAlwaysOnTop(true);//置顶
            this.setLayout(null);//取消内部默认布局
        }
    }
    
    /*
        测试类
     */
    public class Test4 {
        public static void main(String[] args) {
            new JFrameTest();
        }
    }
    

    在这里插入图片描述


    在这里插入图片描述



(3)引用构造方法
  • 格式:

    类名::new
    
  • 范例:

    Student::new
    
  • 练习

    集合里面存储姓名和年龄,比如:张无忌,15

    要求:将数据封装成Student对象并收集到List集合中

    package com.app.demo34_method_reference_test;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.function.Function;
    import java.util.stream.Collectors;
    
    class Student {
        private String name;
        private int age;
    
        public Student() {
    
        }
    
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        // 构造方法
        public Student(String s) {
            this.name = s.split(",")[0];
            this.age = Integer.parseInt(s.split(",")[1]);
        }
    
        /**
         * 获取
         *
         * @return name
         */
        public String getName() {
            return name;
        }
    
        /**
         * 设置
         *
         * @param name
         */
        public void setName(String name) {
            this.name = name;
        }
    
        /**
         * 获取
         *
         * @return age
         */
        public int getAge() {
            return age;
        }
    
        /**
         * 设置
         *
         * @param age
         */
        public void setAge(int age) {
            this.age = age;
        }
    
        public String toString() {
            return "Student{name = " + name + ", age = " + age + "}";
        }
    }
    
    public class Test5 {
        public static void main(String[] args) {
            /*
               练习(引用构造方法):
                 集合里面存储姓名和年龄,比如:张无忌,15
                 要求:将数据封装成Student对象并收集到List集合中
             */
            // 1.创建集合,添加数据
            ArrayList<String> list = new ArrayList<>();
            Collections.addAll(list,
                    "张无忌,15", "周芷若,19", "关羽,23", "甄姬,44");
            System.out.println(list);
    
            // 2.将数据封装成Student对象
            /*List<Student> studentList = list.stream().map(new Function<String, Student>() {
                @Override
                public Student apply(String s) {
                    return new Student(s.split(",")[0], Integer.parseInt(s.split(",")[1]));
                }
            }).collect(Collectors.toList());*/
    
            List<Student> studentList = list.stream()
                    .map(Student::new)  // 引用构造方法
                    .collect(Collectors.toList());
    
            System.out.println(studentList);
        }
    }
    

    在这里插入图片描述


    [张无忌,15, 周芷若,19, 关羽,23, 甄姬,44]
    [Student{name = 张无忌, age = 15}, Student{name = 周芷若, age = 19}, Student{name = 关羽, age = 23}, Student{name = 甄姬, age = 44}]
    
    Process finished with exit code 0
    
    

(4)其他引用方式
  • 使用类名引用成员方法

    • 格式:

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

      String::substring
      
    • 练习

      集合里面一些字符串,要求变成大写后进行输出

      package com.app.demo34_method_reference_test;
      
      import java.util.ArrayList;
      import java.util.Collections;
      import java.util.function.Function;
      
      public class Test6 {
          public static void main(String[] args) {
              /*
                  练习(使用类名引用成员方法):
                    集合里面一些字符串,要求变成大写后进行输出
                    
                  方法引用的规则:
                      1、需要有函数式接口
                      2、被引用的方法必须已经存在
                      3、被引用方法的形参,需要跟抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致
                      4、被引用方法的功能需要满足当前的需求
      
                  抽象方法形参的详解:
                  第一个形参:表示被引用方法的调用者,决定了可以引用哪些类中的方法
                            在Stream流当中,第一个参数一般表示流里面的每一个数据
                            假设流里面的数据是字符串,那么使用这种方式进行方法引用,只能引用String这个类中的方法
      
                  第二个形参到最后一个形参:跟被引用方法的形参保持一致,
                  					  如果没有第二个形参,说明被引用的方法需要是无参的成员方法
      
                  局限性:
                      不能引用所有类中的成员方法。
                      是跟抽象方法的第一个参数有关,这个参数是什么类型的,那么就只能引用这个类中的方法
               */
               */
              // 1.创建集合,添加数据
              ArrayList<String> list = new ArrayList<>();
              Collections.addAll(list, "abc", "AAA", "bbb");
      
              // 2.要求变成大写后进行输出
              /*list.stream().map(new Function<String, String>() {
                  @Override
                  public String apply(String s) {
                      return s.toUpperCase();
                  }
              }).forEach(s -> System.out.println(s));*/
              
              list.stream()
                      .map(String::toUpperCase)   // 使用类名引用成员
                      .forEach(s -> System.out.println(s));
          }
      }
      
      ABC
      AAA
      BBB
      
      Process finished with exit code 0
      
      

  • 引用数组的构造方法

    • 格式:

      数据类型[]::new
      
    • 范例:

      int[]::new
      
    • 练习

      集合中存储一些整数,收集到数组当中。

      package com.app.demo34_method_reference_test;
      
      import java.util.ArrayList;
      import java.util.Arrays;
      import java.util.Collection;
      import java.util.Collections;
      import java.util.function.IntFunction;
      import java.util.function.Supplier;
      import java.util.stream.Collectors;
      
      public class Test7 {
          public static void main(String[] args) {
              /*
                  练习:引用数组的构造方法
                    集合中存储一些整数,收集到数组当中。
      
                  细节:
                      数组的类型,需要跟流中数据的类型保持一致。
               */
              // 1.创建集合,添加数据
              ArrayList<Integer> list = new ArrayList<>();
              Collections.addAll(list, 1, 3, 2, 9, 5, 6);
      
              // 2.收集到数组当中
              /*Integer[] arr = list.stream().toArray(new IntFunction<Integer[]>() {
                  @Override
                  public Integer[] apply(int value) {
                      return new Integer[value];
                  }
              });*/
      
              Integer[] arr = list.stream()
                      .toArray(Integer[]::new); // 引用数组的构造方法
      
              System.out.println(Arrays.toString(arr));
          }
      }
      
      [1, 3, 2, 9, 5, 6]
      
      Process finished with exit code 0
      
      


小结

1、引用静态方法的格式?

类名::静态方法

2、引用成员方法的格式?

引用其他类 ——> 对象::成员方法
引用本类  ——>  this::成员方法
引用父类  ——>  super::成员方法

3、引用构造方法的格式?

类名::new

4、如何使用类名引用成员方法,注意点是什么?

  • 格式

    类名::成员方法
    
  • 注意点:

    • 不能引用所有类中的成员方法
    • 如果抽象方法的第一个参数是A类型的,那就只能引用A类中的成员方法

5、如何引用数组的构造方法?

数据类型[]::new


5、综合小练习
练习1
  • 集合中存储一些字符串的数据,比如:张三,23
  • 要求:收集到Student类型的数组当中(使用方法引用完成)
package com.app.demo34_method_reference_test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

/*
	学生类
*/
class Student {
    private String name;
    private int age;

    public Student() {

    }

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

    // 引用构造方法
    public Student(String s) {
        this.name = s.split(",")[0];
        this.age = Integer.parseInt(s.split(",")[1]);
    }

    /**
     * 获取
     *
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     *
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     *
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     *
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}


public class Test8 {
    public static void main(String[] args) {
        /*
            方法引用的综合小练习:
            练习1:
              集合中存储一些字符串的数据,比如:张三,23
              要求:收集到Student类型的数组当中(使用方法引用完成)
         */
        // 1.创建集合,添加数据
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张三,23", "李四,24", "王五,25");
        System.out.println(list);

        // 2.收集到Student类型的数组当中
        Student[] stuArr = list.stream()
                .map(Student::new)         // 先将String 转换成 Student对象
                .toArray(Student[]::new);  // 再将Student对象 收集到 数组中
        
        System.out.println(Arrays.toString(stuArr));
    }
}
[张三,23, 李四,24, 王五,25]
[Student{name = 张三, age = 23}, Student{name = 李四, age = 24}, Student{name = 王五, age = 25}]

Process finished with exit code 0


练习2
  • 创建集合添加学生对象,学生对象属性:name,age
  • 要求:只获取姓名并放到数组当中(使用方法引用完成)
package com.app.demo34_method_reference_test;

import java.util.ArrayList;
import java.util.Arrays;

/*
	学生类
*/
class Student {
    private String name;
    private int age;

    public Student() {

    }

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

    // 引用构造方法
    public Student(String s) {
        this.name = s.split(",")[0];
        this.age = Integer.parseInt(s.split(",")[1]);
    }

    /**
     * 获取
     *
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     *
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     *
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     *
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}



public class Test9 {
    public static void main(String[] args) {
        /*
            方法引用的综合小练习
            练习2:
               创建集合添加学生对象,学生对象属性:name,age
               要求:只获取姓名并放到数组当中(使用方法引用完成)
         */
        // 1.创建集合,添加数据
        ArrayList<Student> list = new ArrayList<>();
        list.add(new Student("张三丰", 34));
        list.add(new Student("杨幂", 32));
        list.add(new Student("孙悟空", 94));
        list.add(new Student("龙皮", 56));

        System.out.println(list);

        // 2.只获取姓名并放到数组当中
        String[] arr = list.stream()
                .map(Student::getName)      // 先将Student对象 转换成 String,然后只获取姓名
                .toArray(String[]::new);    // 最后将姓名信息放到数组中

        System.out.println(Arrays.toString(arr));
    }
}
[Student{name = 张三丰, age = 34}, Student{name = 杨幂, age = 32}, Student{name = 孙悟空, age = 94}, Student{name = 龙皮, age = 56}]
[张三丰, 杨幂, 孙悟空, 龙皮]

Process finished with exit code 0


练习3:
  • 创建集合添加学生对象,学生对象属性:name,age
  • 要求:把姓名和年龄拼接成:张三-23的字符串,并放到数组当中(使用方法引用完成)
package com.app.demo34_method_reference_test;

import java.util.ArrayList;
import java.util.Arrays;

class Student {
    private String name;
    private int age;

    public Student() {

    }

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

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


    /*
        方法引用:
            1、引用处需要是函数式接口
            2、被引用的方法必须已经存在
            3、被引用的方法的形参和返回值必须与需要跟抽象方法保持一致
            4、被引用的方法的功能需要满足当前的需求
     */
    // 引用静态方法
    public static String StringJoint(Student student) {
        return student.getName() + "-" + student.getAge();
    }


    /**
     * 获取
     *
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     *
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     *
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     *
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}


public class Test10 {
    public static void main(String[] args) {
        /*
            方法引用的综合小练习
            练习3:
               创建集合添加学生对象,学生对象属性:name,age
               要求:把姓名和年龄拼接成:张三-23的字符串,并放到数组当中(使用方法引用完成)
         */
        // 1.创建集合,添加数据
        ArrayList<Student> list = new ArrayList<>();
        list.add(new Student("张三", 13));
        list.add(new Student("李四", 14));
        list.add(new Student("王五", 15));
        list.add(new Student("铁蛋", 23));
        list.add(new Student("赵六", 11));

        list.forEach(s -> System.out.println(s));

        // 2.把姓名和年龄拼接成:张三-23的字符串,并放到数组当中
        String[] arr = list.stream()
                // 先将Student对象 转换成 String,然后在Student类中定义静态方法StringJoint,按照要求拼接:姓名-年龄
                .map(Student::StringJoint)
                // 最后将拼接结果放到数组中
                .toArray(String[]::new);

        System.out.println(Arrays.toString(arr));
    }
}
Student{name = 张三, age = 13}
Student{name = 李四, age = 14}
Student{name = 王五, age = 15}
Student{name = 铁蛋, age = 23}
Student{name = 赵六, age = 11}
[张三-13, 李四-14, 王五-15, 铁蛋-23, 赵六-11]

Process finished with exit code 0


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值