我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java方法引用原理实例解析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java方法引用原理实例解析

在使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿什么参数做什么操作。那么考虑 一种情况:如果我们在Lambda中所指定的操作方案,已经有地方存在相同方案,那是否还有必要再写重复逻辑?

冗余的Lambda场景

在 Printable 接口当中唯一的抽象方法 print 接收一个字符串参数,目的就是为了打印显示它。那么通过Lambda 来使用它的代码很简单:


public class Demo1 {
    private static void printString(Printable data) {
        data.print("Hello, World!");
    }
    public static void main(String[] args) { 
        printString(s -> System.out.println(s));
    }
}
interface Printable {
    void print(String str);
}

其中 printString 方法只管调用 Printable 接口的 print 方法,而并不管 print 方法的具体实现逻辑会将字符串打印到什么地方去。而 main 方法通过Lambda表达式指定了函数式接口 Printable 的具体操作方案为:拿到 String(类型可推导,所以可省略)数据后,在控制台中输出它。

问题分析

这段代码的问题在于,对字符串进行控制台打印输出的操作方案,明明已经有了现成的实现,那就是 System.out 对象中的 println(String) 方法。既然Lambda希望做的事情就是调用 println(String) 方法,那何必自己手动调用呢?

用方法引用改进代码

能否省去Lambda的语法格式(尽管它已经相当简洁)呢?只要“引用”过去就好了:


public class Demo2 {
    private static void printString(Printable data) {
        data.print("Hello, World!");
    }
    public static void main(String[] args) { 
        printString(System.out::println);
    }
}

请注意其中的双冒号 :: 写法,这被称为“方法引用”,而双冒号是一种新的语法。

方法引用符

双冒号 :: 为引用运算符,而它所在的表达式被称为方法引用。如果Lambda要表达的函数方案已经存在于某个方法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。

语义分析:

例如上例中, System.out 对象中有一个重载的 println(String) 方法恰好就是我们所需要的。那么对于 printString 方法的函数式接口参数,对比下面两种写法,完全等效:

Lambda表达式写法: s -> System.out.println(s);
方法引用写法: System.out::println

第一种语义是指:拿到参数之后经Lambda之手,继而传递给 System.out.println 方法去处理。

第二种等效写法的语义是指:直接让 System.out 中的 println 方法来取代Lambda。

两种写法的执行效果完全一样,而第二种方法引用的写法复用了已有方案,更加简洁。

注:Lambda 中 传递的参数 一定是方法引用中 的那个方法可以接收的类型,否则会抛出异常

通过对象名引用成员方法


public class Demo3 {
    private static void printString(printable lambda) {
        lambda.print("Hello");
    }
    public static void main(String[] args) {
        MethodRefObject obj = new MethodRefObject();
        printString(obj::printUpperCase);
    }
}
@FunctionalInterface
interface printable {
    void print(String str);
}
class MethodRefObject {
    public void printUpperCase(String str) {
        System.out.println(str.toUpperCase());
    }
}

通过类名称引用静态方法


public class Demo4 {
    private static void method(int num, Calcable lambda) {
        System.out.println(lambda.calc(num));
    }
    public static void main(String[] args) {
        method(-10, Math::abs);
    }
}
@FunctionalInterface
interface Calcable {
    int calc(int num);
}

通过super引用成员方法


public class Demo5 extends Human{
    @Override public void sayHello() {
        System.out.println("大家好,我是Man!");
    }
    //定义方法method,参数传递Greetable接口
    public void method(Greetable g){
        g.greet();
    }
    public void show(){
        method(super::sayHello);
    }
}
class Human {
    public void sayHello() {
        System.out.println("Hello!");
    }
}
@FunctionalInterface
interface Greetable {
    void greet();
}

通过this引用成员方法


public class Demo6 {
     private void buyHouse() {
         System.out.println("买房子");
     }
     private void marry(Richable lambda) {
         lambda.buy();
     }
     public void beHappy() {
         marry(() -> this.buyHouse());
     }
}
@FunctionalInterface 
interface Richable {
    void buy();
}

类的构造器引用


public class Demo7 {
    public static void printName(String name, PersonBuilder builder) {
        System.out.println(builder.buildPerson(name).getName());
    }public static void main(String[] args) {
        printName("赵丽颖", Person::new);
    }
}
class Person{
    String name;
    public Person(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
interface PersonBuilder { 
    Person buildPerson(String name); 
}

数组的构造器引用


public class Demo8 {
    private static int[] initArray(int length, ArrayBuilder builder) {
        return builder.buildArray(length);
    }
    public static void main(String[] args) {
        int[] array = initArray(10, int[]::new);
    }
}
@FunctionalInterface
interface ArrayBuilder { 
    int[] buildArray(int length); 
}

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注编程网的更多内容!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java方法引用原理实例解析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

mysql索引原理与用法实例分析

本文实例讲述了mysql索引原理与用法。分享给大家供大家参考,具体如下: 本文内容:什么是索引创建索引普通索引唯一索引全文索引单列索引多列索引查看索引删除索引首发日期:2018-04-14什么是索引:索引可以帮助快速查找数据而基本上索引都要
2022-05-29

java LockSupport实现原理示例解析

这篇文章主要为大家介绍了java LockSupport实现原理示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-01-09

Java中HashSet原理及常用方法的示例分析

小编给大家分享一下Java中HashSet原理及常用方法的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一. HashSet概述HashSet是Java集
2023-06-02

Java方法使用实例分析

这篇“Java方法使用实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java方法使用实例分析”文章吧。一、方法的概念
2023-06-30

Java中Scanner用法实例解析

Scanner 指的是java.util包下的Scanner类,可以接收控制台输入的数据,下面这篇文章主要给大家介绍了关于Java中Scanner用法实例的相关资料,文中通过实例代码以及图文介绍的非常详细,需要的朋友可以参考下
2022-11-13

Java Class 解析器实现方法示例

最近在写一个私人项目,名字叫做ClassAnalyzer,ClassAnalyzer的目的是能让我们对Java Class文件的设计与结构能够有一个深入的理解。主体框架与基本功能已经完成,还有一些细节功能日后再增加。实际上JDK已经提供了命
2023-05-31

MyBatisdiscriminator标签原理实例解析

这篇文章主要为大家介绍了MyBatisdiscriminator标签实现原理实例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-02-05

gosyncOnce实现原理示例解析

这篇文章主要为大家介绍了gosyncOnce实现原理示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-01-03

Java方法反射实现原理详解

博主说:Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为 Java 语言的反射机制。在本文中,占小狼分析了 J
2023-05-31

Java中锁的实现原理和实例用法

这篇文章主要介绍“Java中锁的实现原理和实例用法”,在日常操作中,相信很多人在Java中锁的实现原理和实例用法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中锁的实现原理和实例用法”的疑惑有所帮助!
2023-06-16

Java反射机制原理实例分析

今天小编给大家分享一下Java反射机制原理实例分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。什么是反射?反射机制是在运行
2023-06-29

Label Propagation算法原理示例解析

这篇文章主要为大家介绍了Label Propagation算法原理示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-02-01

GTK treeview原理及使用方法解析

GtkTreeView 构件是一个高级的构件,利用他你就可以制作出漂亮的普通列表或者是树状的列表。这个构件里可以包含一或者多行。他的构架呢?正是采用了大名鼎鼎的MVC (Model View Controller) 设计框架。也就是
2022-06-04

Java多线程回调方法实例解析

所谓回调,就是客户程序C调用服务程序S中的某个方法A,然后S又在某个时候反过来调用C中的某个方法B,对于C来说,这个B便叫做回调方法。下面看一个实际例子来理解:本示例设置一个提问者,一个回答者,而回答者需要回答提问者一个很深奥的问题时,这时
2023-05-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录