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的新特性,改进一定是由原因的。希望自己之后可以弥补自己当前的一些肤浅的认识。


相关文章
|
10天前
|
算法 Java Linux
java制作海报二:java使用Graphics2D 在图片上合成另一个照片,并将照片切割成头像,头像切割成圆形方法详解
这篇文章介绍了如何使用Java的Graphics2D类在图片上合成另一个照片,并将照片切割成圆形头像的方法。
21 1
java制作海报二:java使用Graphics2D 在图片上合成另一个照片,并将照片切割成头像,头像切割成圆形方法详解
|
17天前
|
开发框架 IDE Java
java制作游戏,如何使用libgdx,入门级别教学
本文是一篇入门级教程,介绍了如何使用libgdx游戏开发框架创建一个简单的游戏项目,包括访问libgdx官网、设置项目、下载项目生成工具,并在IDE中运行生成的项目。
34 1
java制作游戏,如何使用libgdx,入门级别教学
|
4天前
|
Java Apache Maven
Java将word文档转换成pdf文件的方法?
【10月更文挑战第13天】Java将word文档转换成pdf文件的方法?
12 1
|
8天前
|
Java 编译器
Java“返回类型为 void 的方法不能返回一个值”解决
在 Java 中,如果一个方法的返回类型被声明为 void,那么该方法不应该包含返回值的语句。如果尝试从这样的方法中返回一个值,编译器将报错。解决办法是移除返回值语句或更改方法的返回类型。
|
8天前
|
Java
让星星⭐月亮告诉你,Java NIO之Buffer详解 属性capacity/position/limit/mark 方法put(X)/get()/flip()/compact()/clear()
这段代码演示了Java NIO中`ByteBuffer`的基本操作,包括分配、写入、翻转、读取、压缩和清空缓冲区。通过示例展示了`position`、`limit`和`mark`属性的变化过程,帮助理解缓冲区的工作原理。
17 2
|
8天前
|
安全 Java 测试技术
🌟Java零基础-反射:从入门到精通
【10月更文挑战第4天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
13 2
|
8天前
|
Java
让星星⭐月亮告诉你,jdk1.8 Java函数式编程示例:Lambda函数/方法引用/4种内建函数式接口(功能性-/消费型/供给型/断言型)
本示例展示了Java中函数式接口的使用,包括自定义和内置的函数式接口。通过方法引用,实现对字符串操作如转换大写、数值转换等,并演示了Function、Consumer、Supplier及Predicate四种主要内置函数式接口的应用。
14 1
|
8天前
|
Java
让星星⭐月亮告诉你,Java synchronized(*.class) synchronized 方法 synchronized(this)分析
本文通过Java代码示例,介绍了`synchronized`关键字在类和实例方法上的使用。总结了三种情况:1) 类级别的锁,多个实例对象在同一时刻只能有一个获取锁;2) 实例方法级别的锁,多个实例对象可以同时执行;3) 同一实例对象的多个线程,同一时刻只能有一个线程执行同步方法。
9 1
|
13天前
|
Java 编译器
在Java中,关于final、static关键字与方法的重写和继承【易错点】
在Java中,关于final、static关键字与方法的重写和继承【易错点】
19 5
|
1月前
|
Java
java基础(12)抽象类以及抽象方法abstract以及ArrayList对象使用
本文介绍了Java中抽象类和抽象方法的使用,以及ArrayList的基本操作,包括添加、获取、删除元素和判断列表是否为空。
21 2
java基础(12)抽象类以及抽象方法abstract以及ArrayList对象使用