Java从入门到精通十五(方法引用)

简介: 🍊方法引用的引出在十四篇中介绍过lambda表达式。lambda简化了我们的代码,根据上下文环境,以及语法条件简化了我们的代码。而方法引用语法的出现在lambda的表达式的基础上做出了进一步表达式。点击访问Lambda表达式,回顾上文内容。

🍊方法引用的引出


在十四篇中介绍过lambda表达式。lambda简化了我们的代码,根据上下文环境,以及语法条件简化了我们的代码。而方法引用语法的出现在lambda的表达式的基础上做出了进一步表达式。


点击访问Lambda表达式,回顾上文内容。


我们的lambda的概要格式为(形式参数)->(代码块)。在简化操作的同时我们有时候也需要在lambda表达式进行调用方法。我们采用lambda调用的方法可能已经有了。这个方法可能存在我们的类中,或者接口中。于是我们可以采用方法引用来做进一步的简化。

简单的说,方法引用使用的是已经存在的方法使用。


举一个非常简单易懂的例子🍌


定义一个接口,接口中给出一个方法。


package method;
public interface Printable {
    void printString(String s);
}


然后在测试类中使用


package method;
public class PrintableDemo {
    public static void main(String[] args) {
        usePrintable((String s)->{
            System.out.println(s);
        });
    }
    private  static  void usePrintable(Printable p)
    {
        p.printString("爱生活,爱java");
    }
}


不错,这是一个标准的lambda表达式,当然你也可以去简化参数括号和大括号。

我们的这个lambda调用了System.out的println方法。


很明显这个方法本身就有提供,于是你可以这样去使用


usePrintable(System.out::println);


我么连参数啥的都不用写了。说实话,我一开始看到这样的写法觉得很离谱,但是这个是java8之后的新特性。支持这样的语法。::这个符号代表引用符。我们引用System.out的println方法,然后我们的lambda原来的参数类型和参数就直接传给这个方法去进行处理了。


为什么可以这样写,原因就是可以进行推导出来。可推导的就是可以进行省略的。这样其实和lambda类似。当然,这样的方法引用其实本身就是一个lambda表达式。


在这里我只是说明了这个引用的引出以及和一般的lambda区别的使用。具体的继续说明。 🌼


🍎方法引用类型

🍍 引用静态方法

还是按照完整的代码来举例,不然,单行代码显得太突兀。


我们还是先定义一个接口,这样就好进行对比分析了。


package method;
public interface Converter {
    int convert(String s);
}


测试类


package method;
public class ConverterDemo {
    public static void main(String[] args) {
        //使用lambda表达式
//       useConverter((String s)->
//       {
//            return  Integer.parseInt(s);
//       });
        //优化
        useConverter(s->Integer.parseInt(s));
        //引用类方法
        useConverter(Integer::parseInt);
        //lambda被类方法替代的时候,它的形式参数全部传递给静态方法作为参数
    }
    private  static void useConverter(Converter c)
    {
        int number = c.convert("666");
        System.out.println(number);
    }
}


在这里我们引用了类Integer类的静态方法parseInt方法。传递解释,代码注释说的很明白了。


🍍引用类中实例方法

这样的实例方法还是和静态方法有区别的,虽然引用的时候格式十分相似。静态方法是被类所有的,我们可以直接通过类名去调用,但是实例方法只能通过实例对象去调用。不然是无法去调用。


❗实例化对象我们这样说,类本身是静态的,本身不会占用进程内存,但是在我们实例化的时候会使其拥有动态内存。面向对象的设计中,一般实例化就是为类创建对象的过程。


举个例子


创建一个接口


package method;
public interface MyString {
    String mySubString(String s,int x,int y);
}


测试类的具体使用


package method;
public class MyStringDemo {
    public static void main(String[] args) {
//        useMyString((String s,int x,int y)->
//        {
//            return  s.substring(x,y);
//        });
//        useMyString((s,x,y)->s.substring(x,y));
        //引用类中实例方法
        useMyString(String :: substring);
        //lambda被类的实例方法替代的时候,第一个参数作为调用者,后面的参数全部传递给该方法作为参数
    }
    private static void useMyString(MyString my)
    {
        String s = my.mySubString("Hello", 2, 6);
        System.out.println(s);
    }
}


可以去查看一下源码,substring()方法没有被static修饰,所以不属于类方法,但是属于类对象。也就是实例方法。我们知道String类是一定进行了实例化了。



🍍引用特殊类的方法


有时候我们需要用到某个类的方法,如果你创建对象的时候在你的当前类要用到这个方法,一般是需要实例化对象的,但是如果你不想给出具体的实例,只是想简单的引用。那么就可以根据特殊类进行引用。


其实还是和上面的很类似


我们定义一个接口


package method;
public interface pratice_ {
    void compare(String s1,String s2);
}


测试类


package method;
import java.util.TreeMap;
import java.util.TreeSet;
public class Pratice {
    public static void main(String[] args) {
        usePratice((x,y)->{
            int i = x.compareTo(y);
            System.out.println(i);
        });//lambda常规
        usePratice(String::compareTo);//这样使用
    }
   private static void usePratice(pratice_ m)
    {
        m.compare("Hello","good");
    }
}


🍍引用构造方法


引用构造方法是如何做的呢?我们可以这样。


我们定义一个类


package method;
public class Student {
    private String name;
    private int age;
    public Student()
    {
    }
    public  Student(String name,int age)
    {
        this.age = age;
        this.name = name;
    }
    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;
    }
}


定义一个接口


package method;
public interface StudentBUilder {
    Student build(String name,int age);
}


定义一个测试类


package method;
public class StudentDemo {
    public static void main(String[] args) {
//        useStudentBuilder((String name,int age)->{
//            Student s = new Student(name, age);
//            return s;
//        });
        useStudentBuilder((name,age)->new Student(name,age));
        useStudentBuilder(Student::new);//lambda被构造器替代,它的形式参数全部被传递给构造器作为参数
    }
    private static void useStudentBuilder(StudentBUilder sb)
    {
        Student s = sb.build("jgdabc", 11);
        System.out.println(s.getName()+","+s.getAge());
    }
}


❗可能这样太多的简化写法在一定程度上回造成代码的阅读性不是很好,特别是很难直观看到面向对象的特点。但是存在即合理。java8的新特性,改进一定是由原因的。希望自己之后可以弥补自己当前的一些肤浅的认识。


相关文章
|
3月前
|
消息中间件 Java Kafka
在Java中实现分布式事务的常用框架和方法
总之,选择合适的分布式事务框架和方法需要综合考虑业务需求、性能、复杂度等因素。不同的框架和方法都有其特点和适用场景,需要根据具体情况进行评估和选择。同时,随着技术的不断发展,分布式事务的解决方案也在不断更新和完善,以更好地满足业务的需求。你还可以进一步深入研究和了解这些框架和方法,以便在实际应用中更好地实现分布式事务管理。
|
3月前
|
Java
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
107 9
|
14天前
|
存储 Java 索引
Java快速入门之数组、方法
### Java快速入门之数组与方法简介 #### 一、数组 数组是一种容器,用于存储同种数据类型的多个值。定义数组时需指定数据类型,如`int[]`只能存储整数。数组的初始化分为静态和动态两种: - **静态初始化**:直接指定元素,系统自动计算长度,如`int[] arr = {1, 2, 3};` - **动态初始化**:手动指定长度,系统给定默认值,如`int[] arr = new int[3];` 数组访问通过索引完成,索引从0开始,最大索引为`数组.length - 1`。遍历数组常用`for`循环。常见操作包括求和、找最值、统计特定条件元素等。
|
30天前
|
自然语言处理 Java
Java中的字符集编码入门-增补字符(转载)
本文探讨Java对Unicode的支持及其发展历程。文章详细解析了Unicode字符集的结构,包括基本多语言面(BMP)和增补字符的表示方法,以及UTF-16编码中surrogate pair的使用。同时介绍了代码点和代码单元的概念,并解释了UTF-8的编码规则及其兼容性。
101 60
|
10天前
|
Java
Java快速入门之类、对象、方法
本文简要介绍了Java快速入门中的类、对象和方法。首先,解释了类和对象的概念,类是对象的抽象,对象是类的具体实例。接着,阐述了类的定义和组成,包括属性和行为,并展示了如何创建和使用对象。然后,讨论了成员变量与局部变量的区别,强调了封装的重要性,通过`private`关键字隐藏数据并提供`get/set`方法访问。最后,介绍了构造方法的定义和重载,以及标准类的制作规范,帮助初学者理解如何构建完整的Java类。
|
6天前
|
Java 程序员 调度
Java 高级面试技巧:yield() 与 sleep() 方法的使用场景和区别
本文详细解析了 Java 中 `Thread` 类的 `yield()` 和 `sleep()` 方法,解释了它们的作用、区别及为什么是静态方法。`yield()` 让当前线程释放 CPU 时间片,给其他同等优先级线程运行机会,但不保证暂停;`sleep()` 则让线程进入休眠状态,指定时间后继续执行。两者都是静态方法,因为它们影响线程调度机制而非单一线程行为。这些知识点在面试中常被提及,掌握它们有助于更好地应对多线程编程问题。
37 9
|
11天前
|
安全 Java 程序员
Java面试必问!run() 和 start() 方法到底有啥区别?
在多线程编程中,run和 start方法常常让开发者感到困惑。为什么调用 start 才能启动线程,而直接调用 run只是普通方法调用?这篇文章将通过一个简单的例子,详细解析这两者的区别,帮助你在面试中脱颖而出,理解多线程背后的机制和原理。
43 12
|
12天前
|
算法 Java API
Java 方法注释:规范、实用和高质量的写法
本文深入探讨了如何编写高质量的 Java 方法注释
40 11
|
12天前
|
SQL Java 数据库连接
【潜意识Java】Java中JDBC过时方法的替代方案以及JDBC为什么过时详细分析
本文介绍了JDBC中一些常见过时方法及其替代方案。
35 5
|
2月前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
89 6
Spring Boot 入门:简化 Java Web 开发的强大工具