【从零开始学习JAVA | 第三十篇】方法引用

这篇具有很好参考价值的文章主要介绍了【从零开始学习JAVA | 第三十篇】方法引用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【从零开始学习JAVA | 第三十篇】方法引用,【从零开始学习JAVA】,学习,java

目录

前言:

方法引用:

方法引用基本概念:

方法可以被引用的条件:

方法引用的种类:

方法引用的优点:

总结:


前言:

方法引用作为一个重要的知识点,虽然他使用起来很复杂,而且会降低代码的可读性,但是如果用好了方法引用,我们也会获得不错的效率,因此我们在今天将为大家讲解什么是方法引用。

方法引用:

方法引用基本概念:

【从零开始学习JAVA | 第三十篇】方法引用,【从零开始学习JAVA】,学习,java

我们用一张图就很好的解释了什么叫做方法引用,而官方对于方法引用的定义为:

Java中,方法引用是一种简洁的写法,用于直接引用现有方法,而不是调用它们。它提供了一种更简洁、易读的方式来传递方法作为参数或在函数式接口中使用。

总而言之:方法引用就是我们把已经有的方法拿过来,当作函数式接口中的抽象方法的方法体。

我们举一个例子:

假设要对一个式子进行排序,我们用lambda表达式的写法,可以写为:

Arrays.sort(arr,new Comparator<Integer>(){
    @override
    public int compare (Integer o1 , Integer o2)
    {
    return o2-o1;
    }

});

而如果此时我们的代码中就已经有一个排序的方法 subraction:

public int subraction (int n1.int n2)
{
    return n2-n1;
}

那么我们就可以直接在排序函数中直接拿过来用:

Arrays.sort(arr,方法所在类名::subtraction);

//用我们已经实现的方法subtraction作为排序的规则

其实这就是方法的引用。但是 不是所有的方法都可以引用的!

方法可以被引用的条件:

在Java中,方法引用要满足以下条件才能被引用:

1. 方法引用必须引用一个已存在的方法。也就是说,被引用的方法必须已经被定义。

2. 方法引用的参数类型和数量必须与函数式接口中的抽象方法的参数类型和数量相匹配。也就是说,被引用的方法的参数列表要与函数式接口中的方法参数列表完全匹配。

3. 方法引用的返回类型必须与函数式接口中的抽象方法的返回类型相匹配。也就是说,被引用的方法的返回类型要与函数式接口中的方法返回类型完全匹配。

4. 方法引用必须在上下文中根据目标类型进行推断。也就是说,编译器必须能够根据方法引用的上下文确定需要引用哪个方法。

需要注意的是,方法引用可以用于函数式接口中的抽象方法,包括Lambda表达式和方法引用在内。函数式接口是只有一个抽象方法的接口,可以使用@FunctionalInterface注解来标记。

方法引用的种类:

1.引用静态方法。

        格式:类名::静态方法

        例子:Integer::parseInt

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "1", "2", "3", "4", "5");

        //普通方法
        list.stream().map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                int i = Integer.parseInt(s);
                return i;

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

        //方法引用
        list.stream().map(Integer::parseInt).forEach(s-> System.out.println(s));
    }
}

2.引用成员方法。

        格式:对象::成员方法

        1️⃣其他类:   其他类对象:: 方法名

案例:从一组字符串姓名中选出姓张且名字是三个字的人:

创建其他类:

public class Stringoperation {
    public boolean stringjudge(String s) {
        return s.startsWith("张")&& s.length()==3;
    }
}

引用其他类中的方法:

    public static void main(String[] args) {

        //1.创建集合并添加数据
        ArrayList<String>list= new ArrayList<>();
        Collections.addAll(list,"张无忌","周芷若","张敏","张强","张三丰");

        //普通写法
        list.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).forEach(s-> System.out.println(s));

        //匿名内部类写法
        list.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.startsWith("张")&& s.length()==3;
            }
        }).forEach(s-> System.out.println(s));

        //方法引用
        list.stream().filter(new Stringoperation()::stringjudge).forEach(s-> System.out.println(s));


    }

        2️⃣本类:          this::方法名  (引用处不能是静态方法)

import java.util.function.Consumer;
public class test07 {



        public void doSomething() {
            Consumer<String> consumer = this::printMessage; // 使用this::printMessage引用本类方法
            consumer.accept("Hello, world!");
        }

        public void printMessage(String message) {
            System.out.println(message);
        }

        public static void main(String[] args) {
            test07 obj = new test07();
            obj.doSomething();
        }


}

 TIPS:

        this::方法名  这种形式是不可以在静态main方法中实现的,这是因为main有前缀static,使得main方法变为了静态方法,而静态方法中是没有this指针的,如果想要在静态方法中使用本类方法,就要重新创建一个本类的对象,然后再引用。

public class test06 {
    public static void  main(String[] args) {

        //1.创建集合并添加数据
        ArrayList<String>list= new ArrayList<>();
        Collections.addAll(list,"张无忌","周芷若","张敏","张强","张三丰");

        //方法引用
        list.stream().filter(new test06()::stringjudge).forEach(s-> System.out.println(s));


    }
    public boolean stringjudge(String s) {
        return s.startsWith("张")&& s.length()==3;
    }
}

        3️⃣父类:        super::方法名 (引用处不能是静态方法)                        

class Parent {
    public void printMessage() {
        System.out.println("Hello from Parent class");
    }
}

class Child extends Parent {
    public void printMessage() {
        // 使用super::printMessage引用父类的方法
        Runnable runnable = super::printMessage;
        runnable.run();
    }

    public static void main(String[] args) {
        Child child = new Child();
        child.printMessage();
    }
}

3.引用构造方法。

        格式:类名:: new

        范例:Student :: new

class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public void introduce() {
        System.out.println("Hello, my name is " + name);
    }
}

interface PersonFactory {
    Person create(String name);
}

class Example {
    public static void main(String[] args) {
        // 使用构造方法引用创建Person对象
        PersonFactory factory = Person::new;
        Person person = factory.create("Alice");

        person.introduce();
    }
}

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

        格式:类名::成员方法

        范例:String::substring

public class test08 {
    public static void main(String[] args) {

        //1.创建集合对象并且添加对象
        ArrayList<String> list = new ArrayList<>();

        Collections.addAll(list, "aaa", "bbb", "ccc");

        //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));
    }

}

而使用类名引用成员方法在某些使用规则上与我们最开始的定义不同:

1.被引用方法的形参必须和抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致。

抽象方法形参详解:

第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法                                                              在stream流当中,第一个参数一般都表示流里面的每一个数据。                                                      假设现在流里面的数据是字符串,那么使用这种方式进行方法引用的时候                                        只能使用String这给类中的方法。

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

总而言之:使用类名引用成员方法的时候,并不是所有的类名都可以使用,只可以使用抽象方法中第一个参数对应的类型。

而这也就是这种操作的局限性,它限制了我们可以使用方法的种类!

5.引用数组的构造方法:

        格式:数据类型::new 

        范例:int [] new

        细节:数组的类型需要和流中的数组类型保持一致。

public class test09 {
    public static void main(String[] args) {
        //1.创建集合并添加元素
        ArrayList<Integer> list = new ArrayList<>();

        Collections.addAll(list,1,2,3,4,5,6,7,8,9);

        //2.收集到数组中
            //匿名内部类
       Integer[] arr= list.stream().toArray(new IntFunction<Integer[]>() {
            @Override
            public Integer[] apply(int value) {
                return new Integer[value];
            }
        });

        for (Integer integer : arr) {
            System.out.println(integer);
        }
            //方法引用
        Integer[] array = list.stream().toArray(Integer[]::new);
        for (Integer integer : array) {
         System.out.println(integer);
       }

    }
}

方法引用的优点:

方法引用(Method Reference)是Java中函数式编程的一项重要特性,它允许我们通过方法的名称来引用一个已经存在的方法,可以看作是Lambda表达式的简化形式。方法引用的优点包括:

1. 简洁性:方法引用能够将繁琐的Lambda表达式进一步简化,使代码更加简洁、直观。通过引用现有的方法,避免了再次编写大量的重复代码。

2. 可读性:方法引用能够提高代码的可读性和可理解性。通过使用已有方法的名称,可以更直观地表示代码的意图和逻辑。

3. 代码复用:方法引用使得代码重用更加方便。可以将已存在的、已经实现的方法作为引用直接传递,从而减少了重复的方法定义和实现。

4. 维护性和一致性:使用方法引用可以使代码更具有一致性和易于维护。当需要修改方法逻辑时,只需要修改被引用的方法,而无需修改引用该方法的所有地方。

5. 高效性:方法引用本质上是通过对已经存在的方法进行复用来实现的,因此在执行效率上可能会更高一些。

需要注意的是,方法引用并不是适用于所有场景,它有一些使用限制,比如需要满足函数式接口的要求,被引用的方法与函数式接口的抽象方法有着相同的参数列表和返回类型等。

总结:

        方法引用的出现,进一步优化了lambda表达式的代码逻辑,优化了我们代码的效率,是一个不错的武器,用来提高我们代码的复用性,一致性和高效性,我们要掌握好方法引用这一好武器。

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

【从零开始学习JAVA | 第三十篇】方法引用,【从零开始学习JAVA】,学习,java文章来源地址https://www.toymoban.com/news/detail-609697.html

到了这里,关于【从零开始学习JAVA | 第三十篇】方法引用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【从零开始学习JAVA | 第三十二篇】 异常(下)新手必学!

    目录 前言:  Exceptions(异常): 异常的两大作用: 异常的处理方式: 1.JVM默认处理  2.自己捕获异常 3.抛出处理 自定义异常: 异常的优点: 总结:         前文我们详细的为大家介绍了整个异常体系的框架,本篇我们将为大家介绍 Exceptions 异常,我们会讲解他的作用以及

    2024年02月15日
    浏览(45)
  • 【从零开始学习JAVA | 第三十五篇】IO流综合练习

    目录 前言: 1.拷贝文件(含子文件) 思路: 2.文件加密 思路: 3.修改文件中的数据: 思路: 总结:         在前面我们为大家介绍了FILE类和IO类。这篇文章我们来练习一些综合使用的例子以此来巩固我们自己的所学知识。 建立一个读文件的流来读取文件,一个写文件的流

    2024年02月14日
    浏览(29)
  • 【从零开始学习JAVA | 第四十篇】了解线程池

    目录 前言: 线程池: 线程池的工作流程: 代码实现线程池: 任务拒绝策略:  线程池多大才算合适? 总结:         在Java编程中,线程池是一个强大的工具,它能够管理和复用线程,提供高效的并发处理能力。通过线程池,我们可以有效地控制并发线程的数量,并降

    2024年02月13日
    浏览(46)
  • 【从零开始学习JAVA | 第二十篇】常见API介绍 Math

    目录 前言:  MATH: Math类中的常用方法: 总结:                 本篇往后我们会详细介绍一些常用的API,今天我们介绍的是Math的常用方法。但是其实我们不需要记住所有的方法,在日常工作中自己学会查询API文档就可以了。 Math类是Java中提供的一个标准类, 它包含了许多

    2024年02月15日
    浏览(30)
  • 从零开始学习 Java:简单易懂的入门指南之不可变集合、方法引用(二十六)

    1.1 什么是不可变集合 ​ 是一个长度不可变,内容也无法修改的集合 1.2 使用场景 ​ 如果某个数据不能被修改,把它防御性地拷贝到不可变集合中是个很好的实践。 ​ 当集合对象被不可信的库调用时,不可变形式是安全的。 简单理解: ​ 不想让别人修改集合中的内容 比如

    2024年02月07日
    浏览(38)
  • 【从零开始学习JAVA | 三十九篇】深入多线程

    目录 前言:         ​1.线程的寿命周期​ 2.线程的安全问题 3.锁 同步代码块: 同步方法: 死锁: 4.生产者和消费者模式(等待唤醒机制) 总结:         当今软件开发领域中,多线程编程已成为一项至关重要的技能。然而,要编写出高效、可靠的多线程程序并不容

    2024年02月13日
    浏览(37)
  • 【从零开始学习JAVA | 三十四篇】IO流

    目录 前言: IO流介绍: IO流的常见方法: 1.字节流类: 2.字符流类: 总结:                 IO流就是存入和读取数据的解决方案,并且他是一个知识点很多的章节,因此我们关于IO流的介绍会分为多篇来进行详解,而掌握好IO流可以大大提高我们的效率,简化我们的代码执

    2024年02月13日
    浏览(29)
  • 从零开始学习 Java:简单易懂的入门指南之反射(三十八)

    ​ 专业的解释: ​ 是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法; ​ 对于任意一个对象,都能够调用它的任意属性和方法; ​ 这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。 ​ 通俗的理解: 利用 反射 创建的对象 可

    2024年02月08日
    浏览(31)
  • 从零开始学习 Java:简单易懂的入门指南之线程同步(三十五)

    1.1卖票【应用】 案例需求 某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票 实现步骤 定义一个类SellTicket实现Runnable接口,里面定义一个成员变量:private int tickets = 100; 在SellTicket类中重写run()方法实现卖票,代码步骤如下

    2024年02月08日
    浏览(36)
  • 从零开始学习 Java:简单易懂的入门指南之线程池(三十六)

    当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么Java中的线程存在哪几种状态呢?Java中的线程 状态被定义在了java.lang.Thread.State枚举类中,State枚举类的源码如下: 通过源码我们可以看到Ja

    2024年02月08日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包