System.out::println是什么 ? Lambda表达式和方法引用

System.out::printlin 可以很好的串联Java8新特性中的Lambda表达式和方法引用

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

        //完成对集合元素的遍历输出
        list.forEach(System.out::println);

  1. 首先用Lambda体简化匿名内部类
  2. 了解函数式接口的概念
  3. 方法引用的用法
  4. Consumer<T> 的场景
  5. 引出函数式编程
  6. System.out::println

链条式引出结果, 并非完整文档笔记.

从匿名内部类 到 Lambda

Lambda本质就是一种书写方式 , 他的整体就是一个对象

匿名内部类写法

假如要创建接口对象, 一种方式就是写成匿名内部类 ,
这里匿名的说法, 描述的是不用写一个类来继承Runnable , 进而new对象再去调用这个类重写的run方法

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("这是runnable");
            }
        };

Lambda写法

. 匿名内部类这种方式过于复杂, 可以写成Lambda的格式进行优化

        Runnable runnable1 = () -> {
            System.out.println("这是runnable2");
        };

在这里插入图片描述
相当于将 new Runnable() 和 除了方法内的代码给省略
( ) 就是run( ) 的参数表, 接口名方法名都省了.

更简化的Lambda

当这个方法体中只有一行代码时, 可以直接省略{}括号

        Runnable runnable2 = () -> System.out.println("这是runnable2");

所以Lambda体在Java中是对象

在其它语言中Lambda体或者称之为箭头函数./回调函数, 但在Java中很明显Lambda体是对象, 就是函数式接口的一个对象
( ) 就是接口方法的参数
-> 箭头就是参数要传给谁
方法体, 就是要接受参数并实现的逻辑

在这里插入图片描述
但runnable的run方法是一个无参方法,

  1. 当无参方法时, 写成 ( ) -> 方法体
  2. 当有且只有一个方法参数时写成 arg -> 方法体
  3. 当有多个方法参数时 写成 (arg1,arg2) -> 方法体

函数式接口

函数式接口的定义

只有一个方法的接口为函数式接口 , 类似与线程先关的Runnable 接口, 只有一个run( ) 方法 他就是一个函数式接口 ,
而且接口还有函数式接口检查注解@FunctionalInterface, 来用于检查这个接口是不是函数式接口
在这里插入图片描述

函数式编程

函数式接口的对象是Lambda体,
函数式编程就是是像传递参数一样传递一个Lambda体

举例Thread类, 打开Java中的Threa类 , 发现有一个构造方法, 需要一个参数为Runnable类型
在这里插入图片描述
具体写法就是

        Runnable runnable3 = () -> System.out.println("这是runnable3");

        //new Thread(Runnable r)
        Thread thread = new Thread(runnable3);
        

        thread.start();//结果 : 这是runnable3

这就是实现了函数式编程, 传递过去的参数本质上是一个对象, 对象是Runnable接口的一个实例

函数式接口的分类

在这里插入图片描述

Java中内置了4大类型的函数式接口来适应不同的场景, 主要4种但不限于4种,而且还有众多的子接口

  1. Comsumer<T> accept( T ,t ) 只消费传进来的参数没有返回值
  2. Supplier<T> T get() 不接受参数有返回
  3. Function<T,R> R apply (T, t) 对传进来的对象t操作, 返回R类型
  4. Predicate<T> boolean test(T t)

Consumer 用法

Consumer<String> 表明了accept 方法的参数 为String类型, 就是要把传进去的String类型参数给消费掉
诸如"匿名内部类写法" “Lambda写法”


        //匿名内部类写法
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };

        consumer.accept("匿名内部类写法");
        
        
        //Lambda写法
        Consumer<String> consumer1 = s -> System.out.println(s);
        consumer1.accept("Lambda写法");

Consumer在函数式编程中的使用

例如 集合中的forEach方法就是 一个函数式编程的实现 , 最终也将引出System.out::println
方法要传入一个 Comsumer<T> 的对象
在这里插入图片描述

        //创建一个集合
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
         
        // 这里是完整写法 , 可以吧consumer3直接传进去, 也可以直接写简化版Lambda;
        Consumer<Integer> consumer = new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println(integer);
            }
        };

        //将Lambda体传入 , 也就是函数式编程 , 完成对集合的便利
        list.forEach( s -> System.out.println(s));
      

其实在forEach方法中, 接受到 函数式接口对象, 进行非空判断之后, 也是调用对象里的accept方法对每一个元素进行输出操作
在这里插入图片描述

距离System.out::println仅差一步


        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        //将Lambda体传入 , 也就是函数式编程 , 完成对集合的便利
        list.forEach( s -> System.out.println(s));
        //两种方式等同, 就是方法引用对Lambda表达式的再度简化
        list.forEach(System.out::println)

方法引用

System.out::println 就是一种方法引用的写法
方法引用的条件是 函数式接口的方法参数类型和返回值类型, 与 方法引用的参数类型和方法引用类型相同
则Lambda体可以简化书写为
对象::方法 类似于System.out::println
类:: 静态方法 类似于 Math::round

  • 解读

以list.forEach(Consumer<T> com) 为例子
函数式接口的accetpt方法 参数类型Integer并且无返回值
方法体中的println()方法参数类型也是Integer也无返回值
这种场景下省略参数写法, 直接用对象::方法 , 即 System.out::println
这里Syetem.out 等用于一个PrintStream对象 , 用对象::方法


        //创建一个集合
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
         

        Consumer<Integer> consumer = new Consumer<Integer>() {
            @Override
            //  accect方法参数类型为Integer, 无返回值
            public void accept(Integer integer) {
             // System.out 是一个PrintStream对象 , 调用println()方法 该方法参数类型也是Integer也无返回值
                System.out.println(integer);
            }
        };



        //所以这时候不仅可以写成lambda体
        list.forEach( s -> System.out.println(s));
        //也可以使用方法引用  对象::方法
        list.forEach(System.out::println)

实现细节

  1. list集合是ArrayList的对象, 其顶层接口Collection继承自Iterable接口, 所以可以使用其forEach方法
    在这里插入图片描述
    这里forEach 约定参数Consumer的泛型下限为Integer, 因为调用这个方法的实例对象就是Integer类型的集合
    this就是对象本身, 进行便利 , 调用accept对便利出的数字进行输出.
    在这里插入图片描述
    在System.out 获得的PrintStream对象的引用 , 可以重载到Int输出的方法 , 可以发现参数类型于accept都是Integer,
    返回值都是void , 这样就达成方法引用先决条件
    在这里插入图片描述

总结反思

Lambda表达式实现了代码简化, 也更加实际的完成了函数式编程 ,
假如使用匿名内部类方式以下代码就会报错

        List<String> list = Arrays.asList("1", "2", "3", "4", "5");

        Consumer<Integer> consumer = new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println(integer);
            }
        };

        //报错
        list.forEach(consumer);
        
        //正常使用
        list.forEach(System.out::println);


        

如果使用匿名内部类, Consumer的类型要进行声明, 需要比操作的对象需要什么类型的Consumer都要指定好
那么假如调用类型不固定, 由Integer变成了String , 那么就会出问题. 使用Lambda表达式其类型为自动推导
调用者类型即为Consumer<T> T的类型, 更加灵活.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/285309.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【快速全面掌握 WAMPServer】11.安装 PHP 扩展踩过的坑

网管小贾 / sysadm.cc 我们在调试程序代码时&#xff0c;总会遇到一些 PHP 项目需要某些扩展组件。 而在 WAMPServer 下通常的 PHP 扩展的安装也不算有多麻烦。 具体关于 PHP 扩展的区分&#xff08;比如安全线程或非安全线程&#xff09;&#xff0c;以及怎么安装小伙伴们可…

【Emgu.CV教程】第18篇 、色彩处理之AdaptiveThreshold()自适应阈值化处理

之前学了Threshold()二值化函数&#xff0c;这个是在每一张照片里面&#xff0c;用同一个阈值进行二值化操作&#xff0c;但是对于一些对比度比较大的图片&#xff0c;可能会出现问题。比如这张照片想要提取出黑色文字文字&#xff1a; 如果执行以下代码&#xff1a; CvInvoke…

基于Flutter构建小型新闻App

目录 1. 概述 1.1 功能概述 1.2 技术准备 1.3 源码地址 2. App首页 2.1 pubspec依赖 2.2 热门首页组件 2.2.1 DefaultTabController 2.2.2 Swiper 2.3 新闻API数据访问 2.4 热门首页效果图 3. 新闻分类 3.1 GestureDetector 3.2 新闻分类效果图 4. 收藏功能 4…

详解 MySql InnoDB 的 MVCC 实现机制

目录 一. 前言 二. 认识 MVCC 2.1. 什么是 MVCC&#xff1f; 2.2. 什么是当前读和快照读&#xff1f; 2.3. 当前读、快照读和 MVCC 的关系 2.4. MVCC 能解决什么问题&#xff0c;好处是什么&#xff1f; 2.5. 小结 三. MVCC 的实现原理 3.1. 隐式字段 3.2. undo 日志…

SQL常见面试题

今天刷了一遍牛客里的必知必会题&#xff0c;一共50道题&#xff0c;大部分都比较基础&#xff0c;下面汇总一下易错题。 SQL81 顾客登录名 本题几个关键点&#xff1a; 登录名是其名称和所在城市的组合&#xff0c;因此需要使用substring()和concat()截取和拼接字段。得到登…

SpringBoot解决前后端分离跨域问题:状态码403拒绝访问

最近在写和同学一起做一个前后端分离的项目&#xff0c;今日开始对接口准备进行 登录注册 的时候发现前端在发起请求后&#xff0c;抓包发现后端返回了一个403的错误&#xff0c;解决了很久发现是【跨域问题】&#xff0c;第一次遇到&#xff0c;便作此记录✍ 异常描述 在后端…

前端:html+css+js实现CSDN首页

提前说一下&#xff0c;只实现了部分片段哈&#xff01;如下&#xff1a; 前端&#xff1a;htmlcssjs实现CSDN首页 1. 实现效果2. 需要了解的前端知识3. 固定定位的使用4. js 监听的使用4. 参考代码和运行结果 1. 实现效果 我的实现效果为&#xff1a; 原界面如下,网址为&…

计算机网络(1)

计算机网络&#xff08;1&#xff09; 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 计算机网络和因特网&#xff08;1&#xff09;因特网概念解读服务常见的服务 协议网络边缘特点强调 网络核心特点强调 小程一言 我的计算机网络专栏&#xff0c;是自己在计算机网络…

1. Spring概述

概述 Spring 是一个开源框架Spring 为简化企业级开发而生&#xff0c;使用 Spring&#xff0c;JavaBean 就可以实现很多以前要靠 EJB 才能实现的功能。同样的功能&#xff0c;在 EJB 中要通过繁琐的配置和复杂的代码才能够实现&#xff0c;而在 Spring 中却非常的优雅和简洁。…

软件运维实施维保方案

1.项目情况 2.服务简述 2.1服务内容 2.2服务方式 2.3服务要求 2.4服务流程 2.5工作流程 2.6业务关系 2.7培训 3.资源提供 3.1项目组成员 3.2服务保障 项目开发、管理、实施、运维、结项、验收等全文档获取&#xff1a;软件开发全套资料-CSDN博客

【LeetCode每日一题】1599. 经营摩天轮的最大利润(模拟)—2024新年快乐!

2024-1-1 文章目录 [1599. 经营摩天轮的最大利润](https://leetcode.cn/problems/maximum-profit-of-operating-a-centennial-wheel/)思路&#xff1a; 1599. 经营摩天轮的最大利润 思路&#xff1a; 1.对摩天轮的运转情况进行模拟&#xff0c; 2.遍历数组&#xff0c;分别计…

简单FTP客户端软件开发——JavaFX开发FTP客户端

文章目录 导入外部包commons-net-3.10.0.jarJavaFX开发客户端 FTP客户端要求如下&#xff1a; 简单FTP客户端软件开发 网络环境中的一项基本应用就是将文件从一台计算机中复制到另一台可能相距很远的计算机中。而文件传送协议FTP是因特网上使用得最广泛的文件传送协议。FTP使用…

Golang leetcode707 设计链表 (链表大成)

文章目录 设计链表 Leetcode707不使用头节点使用头节点 推荐** 设计链表 Leetcode707 题目要求我们通过实现几个方法来完成对链表的各个操作 由于在go语言中都为值传递&#xff0c;&#xff08;注意这里与值类型、引用类型的而区别&#xff09;&#xff0c;所以即使我们直接在…

RocketMQ 生产者源码分析:DefaultMQProducer、DefaultMQProducerImpl

&#x1f52d; 嗨&#xff0c;您好 &#x1f44b; 我是 vnjohn&#xff0c;在互联网企业担任 Java 开发&#xff0c;CSDN 优质创作者 &#x1f4d6; 推荐专栏&#xff1a;Spring、MySQL、Nacos、Java&#xff0c;后续其他专栏会持续优化更新迭代 &#x1f332;文章所在专栏&…

【面试】面向对象编程的三大概念(实例辅助记忆)

【面试】面向对象编程的三大概念&#xff08;实例辅助记忆&#xff09; 虑面向对象编程的三大特性&#xff0c;它们是&#xff1a; 封装&#xff08;Encapsulation&#xff09;&#xff1a; 将对象的状态和行为封装在一起&#xff0c;对外部隐藏对象的内部实现细节。这样可以防…

Nginx 简介和入门 - part1

虽然作为1个后端程序员&#xff0c; 终究避不开这东西 安装Nginx 本人的测试服务器是debian &#xff0c; 安装过程跟ubuntu基本一样 sudo apt-get install nginx问题是 nginx 安装后 执行文件在/usr/sbin 而不是/usr/bin 所以正常下普通用户是无法使用的。 必须切换到root…

事件循环的理解

1.单线程 Js是一个单线程的语言,代码只能一行一行去执行,遇到同步的代码就直接执行了,如果遇到异步的代码怎么办&#xff1f; 不可能等到异步的代码执行完&#xff0c;在去执行后面同步的代码。 2.主线程 遇到同步的代码,就在主线程里面直接执行了。 3.任务队列 遇到异步的…

数位dp详解,记忆化搜索,递推,OJ精讲

文章目录 前言引例-不降数前置知识差分转换枚举技巧前缀状态 状态分析状态设计状态转移初始状态记忆化搜索 引例代码实现状态初始化数位初始化记忆化搜索 非递归如何实现&#xff1f;状态设计状态转移算法原理算法实现初始化递推求解 OJ精讲Good Numbers不要62不含连续1的非负整…

redis 从0到1完整学习 (十四):RedisObject 之 ZSet 类型

文章目录 1. 引言2. redis 源码下载3. redisObject 管理 ZSet 类型的数据结构4. 参考 1. 引言 前情提要&#xff1a; 《redis 从0到1完整学习 &#xff08;一&#xff09;&#xff1a;安装&初识 redis》 《redis 从0到1完整学习 &#xff08;二&#xff09;&#xff1a;re…

【基础】【Python网络爬虫】【1.认识爬虫】什么是爬虫,爬虫分类,爬虫可以做什么

Python网络爬虫基础 认识爬虫1.什么是爬虫2.爬虫可以做什么3.为什么用 Ptyhon 爬虫4.爬虫的分类通用爬虫聚焦爬虫功能爬虫增量式爬虫分布式爬虫 5.爬虫的矛与盾&#xff08;重点&#xff09;6.盗亦有道的君子协议robots7.爬虫合法性探究 认识爬虫 1.什么是爬虫 网络爬虫&…