Java基础学习(十三)

Java基础学习(十三):方法引用

本文为个人学习记录,内容学习自 黑马程序员


概念

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

  • 方法引用的前提:

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

    public class Test {
        public static void main(String[] args) {
            Integer[] arr = {3, 5, 4, 1, 6, 2};
            // 方法一:匿名内部类实现接口
            Arrays.sort(arr, new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o2 - o1;
                }
            });
    
            // 方法二:Lambda表达式简化匿名内部类
            Arrays.sort(arr, (o1, o2) ->  o2 - o1);
    
            // 方法三:引用已有的方法,将该方法作为抽象方法的方法体,::为方法引用符
            Arrays.sort(arr, Test::subtraction);
        }
    
        // 被引用方法可以是Java已经写好的,也可以来自一些第三方工具类
        public static int subtraction(int a, int b) {
            return b - a;
        }
    }
    

引用静态方法

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

  • 示例:将字符串组成的集合 ["1", "2", "3", "4", "5"] 转换成整数组成的集合 [1, 2, 3, 4, 5]

    ArrayList<String> list = new ArrayList<>();
    Collections.addAll(list, "1", "2", "3", "4", "5");
    // 方法一:传统方法
    List<Integer> newList = list.stream().map(new Function<String, Integer>() {
        @Override
        public Integer apply(String s) {
            return Integer.parseInt(s);
        }
    }).collect(Collectors.toList());
    
    // 方法二:由于匿名内部类中抽象方法实现的功能和Integer中的静态方法parseInt完全一致,因此可以通过方法的引用简化代码
    List<Integer> newList2 = list.stream().map(Integer::parseInt).collect(Collectors.toList());
    

引用成员方法

  • 格式:对象::成员方法

    • 引用其他类的成员方法:其他类对象::方法名
    • 引用本类的成员方法:this::方法名
    • 引用父类的成员方法:super::方法名
  • 示例:

    • 引用其他类的成员方法

      public class Test {
          public static void main(String[] args) {
              ArrayList<String> list = new ArrayList<>();
              Collections.addAll(list, "a", "b", "c", "ac", "abc");
              // new Operator()创建了一个其他类(此处是自定义的Operator类)的对象
              // judge是其他类的成员方法,其功能与filter的形参 函数式接口Predicate 的抽象方法一致
              list.stream().filter(new Operator()::judge).forEach(s -> System.out.println(s));
          }
      }
      
      class Operator {
          public boolean judge(String s) {
              return s.startsWith("a");
          }
      }
      
    • 引用本类的成员方法

      public class Test {
          public static void main(String[] args) {
              ArrayList<String> list = new ArrayList<>();
              Collections.addAll(list, "a", "b", "c", "ac", "abc");
              // 此处并不是采用this::方法名,这是因为静态方法内部只能访问到静态方法,无法使用this关键字!
              list.stream().filter(new Test()::judge).forEach(s -> System.out.println(s));
          }
      
          public boolean judge(String s) {
              return s.startsWith("a");
          }
      }
      
    • 引用父类的成员方法

      public class Test extends Operator{
          public static void main(String[] args) {
              new Test().test();
          }
          public void test() {
              ArrayList<String> list = new ArrayList<>();
              Collections.addAll(list, "a", "b", "c", "ac", "abc");
              // 通过super引用父类方法
              list.stream().filter(super::judge).forEach(s -> System.out.println(s));
          }
      }
      
      class Operator {
          public boolean judge(String s) {
              return s.startsWith("a");
          }
      }
      

引用构造方法

  • 格式:类名::new
  • 作用:创建对象
  • 注意事项:
    • 构造方法的形参需要和抽象方法一致
    • 构造方法没有返回值,因此只要抽象方法的返回值类型为构造方法所在类即可

其他调用方式

  1. 使用类名引用成员方法

    • 格式:类名::成员方法

    • 规则:

      • 形参的规则和其他引用不同,其他的规则一致
      • 被引用方法的调用者需要跟抽象方法的第一个形参对应,例如抽象方法的第一个形参是 String 类型,那么只能引用 String 中的方法
      • 被引用方法的形参需要跟抽象方法的第二个形参到最后一个形参保持一致
    • 示例:集合里面包含一些字符串,将其变成大写后进行输出

      ArrayList<String> list = new ArrayList<>();
      Collections.addAll(list, "aaa", "bbb", "ccc");
      // 方法一:完整版
      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));
      
  2. 引用数组的构造方法

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

    • 规则:

      • 形参的规则和其他引用不同,其他的规则一致

      • 不需要保证形参一致,只要数组类型和流中的数据一致即可

    • 示例:集合中存储一些整数,收集到数组中

      ArrayList<Integer> list = new ArrayList<>();
      Collections.addAll(list, 1, 2, 3, 4, 5);
      // 方法一:完整版
      Integer[] arr1 = list.stream().toArray(new IntFunction<Integer[]>() {
          @Override
          public Integer[] apply(int value) {
              return new Integer[value];
          }
      });
      
      // 方法二:简化版(采用方法引用)
      Integer[] arr2 = list.stream().toArray(Integer[]::new);
      
posted @   victoria6013  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示