Java——方法的引用

简介: 方法引用允许将已有方法作为函数式接口的实现。使用“::”符号,需具备函数式接口,被引用的方法须存在且参数和返回值需与抽象方法一致。其分类包括:静态方法引用(类::方法名)、成员方法引用(对象::方法名、this::方法名、super::方法名)和构造方法引用(类名::new)。方法引用提高了代码的简洁性和可读性,减少了样板代码。

🍁1. 方法引用

方法的引用:把已经存在的方法拿来使用,当作函数式接口中抽象方法的方法体

" :: "是方法引用符

方法引用时需要注意:

1. 需要有函数式接口

2. 被引用的方法必须存在

3. 被引用的方法的形参和返回值要和抽象方法保持一致

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

以Arrays中的静态方法 sort() 为例,其中的参数就是一个函数式接口,先来用匿名内部类和lambda的方式演示一下

需求:把数组中的元素降序排列

public class Demo1 {
    public static void main(String[] args) {
        //把数组中的内容倒序排列
        Integer[] arr = {2, 1, 4, 5, 3};
        //匿名内部类的方式
        Arrays.sort(arr, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        // lambda表达式
        Arrays.sort(arr, (Integer o1, Integer o2) -> {
            return o2 - o1;
        });
        // lambda表达式简化版本
        Arrays.sort(arr, (o1, o2) -> o2 - o1);
        System.out.println(Arrays.toString(arr));
    }
}

接下来看方法引用的方式

public class Demo1 {
    public static void main(String[] args) {
        //把数组中的内容倒序排列
        Integer[] arr = {2, 1, 4, 5, 3};
        //方法引用
        Arrays.sort(arr, Demo1::subtraction);
        System.out.println(Arrays.toString(arr));
    }
    public static int subtraction(int num1, int num2) {
        return num2 - num1;
    }
}

🍁2. 方法引用的分类

🍁2.1 引用静态方法

格式: 类 :: 方法名

需求:获取集合中的数字部分

如果说使用之前的方法来解决,就是再定义一个集合,在循环中调用parseInt()方法,再把结果添加到新集合中

public class Demo2 {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        Collections.addAll(arrayList, "1", "2", "3", "4");
        //匿名内部类方式
        arrayList.stream().map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                int res = Integer.parseInt(s);
                return res;
            }
        }).forEach(s -> System.out.print(s));
        System.out.println();
        //方法引用
        arrayList.stream().map(Integer::parseInt).forEach(s -> System.out.print(s));
    }
}

这里正好符合方法引用的条件

🍁2.2 引用成员方法

格式:

其他类:其他类的对象 :: 方法名

本类中:this :: 方法名

父类中:super :: 方法名

需求:找出集合中以 'a' 开头并且长度大于2的字符串

这里在另一个类中定义了一个专门进行字符串判断的方法,并且参数类型和返回值都和用到的抽象方法一致,这时就可以使用方法引用了

🍁2.3 引用构造方法

格式:类名 :: new

需求:把集合中的字符串封装成Student对象收集到List集合中

public 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]);
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class Demo4 {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        Collections.addAll(arrayList, "张三,23", "李四,21", "王五,21");
        //把集合中的字符串封装成Student对象收集到List集合中
        //之前stream流的写法
        List<Student> list1 = arrayList.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());
        System.out.println(list1);
        //引用构造方法
        List<Student> list2 = arrayList.stream().map(Student::new).collect(Collectors.toList());
        System.out.println(list2);
    }
}

在使用引用构造方法的时候,由于需要保证被引用的方法的形参和返回值要和抽象方法保持一致,所以要重新再写一个符合条件的构造方法才可以

🍁3. 使用类名引用成员方法

这里的规则是要稍微变一下的,在刚开始提到的第三条中 “被引用的方法的形参和返回值要和抽象方法保持一致” 要更改为被引用方法的形参要和抽象方法的第二个参数到最后一个形参保持一致,返回值需要保持一致

对于抽象方法中的形参:第一个参数表示被引用方法的调用者,决定了可以引用哪些类中的方法,在Stream流中,第一个参数一般都表示流里面的每一个数据,如果说流里面的是字符串类型,那么使用这种方式进行方法引用,只能用String这个类中的方法

第二个参数到最后一个参数,需要和引用方法的形参保持一致,如果没有第二个参数,说明被引用的方法需要是无参的成员方法

public class Demo5 {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        Collections.addAll(arrayList, "aaa", "bbb", "ccc", "ddd");
        //把集合中的字符串变为大写之后进行输出
        arrayList.stream().map(new Function<String, String>() {
            @Override
            public String apply(String s) {
                return s.toUpperCase();
            }
        }).forEach(s -> System.out.print(s + " "));
        System.out.println();
        //方法引用
        arrayList.stream().map(String::toUpperCase).forEach(s -> System.out.print(s + " "));
    }
}

这里抽象方法的方法体只有一个参数,引用的方法需要是无参的成员方法

🍁4. 引用数组的构造方法

引用数组的构造方法就是为了创建一个数组,创建的数组类型要和流中的数据类型保持一致

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

需求:把集合中的数据收集起来放在数组中

public class Demo6 {
    public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        Collections.addAll(arrayList,1,2,3,4,5);
        //匿名内部类方式
        Integer[] array1 = arrayList.stream().toArray(new IntFunction<Integer[]>() {
            @Override
            public Integer[] apply(int value) {
                return new Integer[value];
            }
        });
        System.out.println(Arrays.toString(array1));
        //数组引用构造方法
        Integer[] array2 = arrayList.stream().toArray(Integer[]::new);
        System.out.println(Arrays.toString(array2));
    }
}

🍁5. 方法引用的优点

简洁性:方法引用通常比Lambda表达式更简洁,特别是当Lambda表达式只是简单地调用一个已存在的方法时。

可读性:对于熟悉的方法名,方法引用比Lambda表达式更容易理解。

减少样本模板:方法引用减少了编写Lambda表达式时的样板代码,使代码更加清晰。


目录
打赏
0
12
13
1
94
分享
相关文章
在Java中实现分布式事务的常用框架和方法
总之,选择合适的分布式事务框架和方法需要综合考虑业务需求、性能、复杂度等因素。不同的框架和方法都有其特点和适用场景,需要根据具体情况进行评估和选择。同时,随着技术的不断发展,分布式事务的解决方案也在不断更新和完善,以更好地满足业务的需求。你还可以进一步深入研究和了解这些框架和方法,以便在实际应用中更好地实现分布式事务管理。
|
3月前
|
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
114 9
Java快速入门之数组、方法
### Java快速入门之数组与方法简介 #### 一、数组 数组是一种容器,用于存储同种数据类型的多个值。定义数组时需指定数据类型,如`int[]`只能存储整数。数组的初始化分为静态和动态两种: - **静态初始化**:直接指定元素,系统自动计算长度,如`int[] arr = {1, 2, 3};` - **动态初始化**:手动指定长度,系统给定默认值,如`int[] arr = new int[3];` 数组访问通过索引完成,索引从0开始,最大索引为`数组.length - 1`。遍历数组常用`for`循环。常见操作包括求和、找最值、统计特定条件元素等。
Java容器及其常用方法汇总
Java Collections框架提供了丰富的接口和实现类,用于管理和操作集合数据。
Java容器及其常用方法汇总
|
12天前
|
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
45 3
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
|
10天前
|
java.time常用方法汇总
`java.time` API 是从 Java 8 开始引入的时间日期处理库,旨在替代老旧的 `java.util.Date` 和 `Calendar`。它提供了更简洁、强大和灵活的方式处理日期、时间、时区及时间间隔,支持全球化和时间计算需求。API 包含获取当前时间、创建指定时间、解析和格式化字符串、进行加减运算、比较时间、获取年月日时分秒、计算时间间隔、时区转换以及判断闰年等功能。示例代码展示了如何使用这些功能,极大简化了开发中的时间处理任务。
Java快速入门之类、对象、方法
本文简要介绍了Java快速入门中的类、对象和方法。首先,解释了类和对象的概念,类是对象的抽象,对象是类的具体实例。接着,阐述了类的定义和组成,包括属性和行为,并展示了如何创建和使用对象。然后,讨论了成员变量与局部变量的区别,强调了封装的重要性,通过`private`关键字隐藏数据并提供`get/set`方法访问。最后,介绍了构造方法的定义和重载,以及标准类的制作规范,帮助初学者理解如何构建完整的Java类。
Java 高级面试技巧:yield() 与 sleep() 方法的使用场景和区别
本文详细解析了 Java 中 `Thread` 类的 `yield()` 和 `sleep()` 方法,解释了它们的作用、区别及为什么是静态方法。`yield()` 让当前线程释放 CPU 时间片,给其他同等优先级线程运行机会,但不保证暂停;`sleep()` 则让线程进入休眠状态,指定时间后继续执行。两者都是静态方法,因为它们影响线程调度机制而非单一线程行为。这些知识点在面试中常被提及,掌握它们有助于更好地应对多线程编程问题。
63 9
Java面试必问!run() 和 start() 方法到底有啥区别?
在多线程编程中,run和 start方法常常让开发者感到困惑。为什么调用 start 才能启动线程,而直接调用 run只是普通方法调用?这篇文章将通过一个简单的例子,详细解析这两者的区别,帮助你在面试中脱颖而出,理解多线程背后的机制和原理。
68 12
Java 方法注释:规范、实用和高质量的写法
本文深入探讨了如何编写高质量的 Java 方法注释
63 11

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等