JDK8新特性【接口新特征、lambda语法、Supplier、Consumer、Function、Predicate】

目录

  • 一、关于接口的新特性
    • 1.1 jdk1.8之前的接口重要特性
    • 1.2 JDK8以后
        • 代码演示
    • 1.3 总结
        • 通过代码演示发现
        • 作用
  • 二、Lambda表达式[重点]
    • 2.1 将匿名内部类写法改写为lambda写法
    • 2.2 语法特点
        • 能够写成lambda形式的的前提
        • 语法特征
        • 代码演示
        • 深入理解lambda
    • 2.3 总结
  • 三、函数式接口
  • 3.1 概念
        • 什么是函数式接口
    • 四个典型的函数式接口
    • 3.2 Supplier
    • 3.3 Consumer
    • 3.4 Function
    • 3.5 Predicate
    • 3.6 总结
    • 思维导图
    • 最后

一、关于接口的新特性

1.1 jdk1.8之前的接口重要特性

  • 方法全都是抽象方法,即都没有方法体

1.2 JDK8以后

  • 允许接口中有被default和static修饰的方法带方法体
代码演示

接口USB

public interface USB {/** jdk8之前接口中只能有抽象方法* jdk8之后接口中被default的方法不是抽象方法,可以被重写,也可以不重写,不强制* 且方法还可以被static修饰,不能被重写,调用,只能通过接口调用*/int a =1;void fun1();// 默认抽象方法default void funNew(){// 被default修饰方法System.out.println("JDK8新特性:default修饰的方法要有方法体,实现类不强制重写");}static void funNew2(){// 被static修饰方法System.out.println("JDK8新特性:static修饰的方法要有方法体,实现类不可重写,不可调用,通过接口直接调用");}
}

实现类USBImpl

public class USBImpl implements USB{@Overridepublic void fun1() {System.out.println("重写旧方法");}@Overridepublic void funNew() {  //可以重写default修饰的方法}}

测试

public class USBImplTest {public static void main(String[] args) {USBImpl usb = new USBImpl();usb.fun1();usb.funNew();//usb.funNew2(); //实现类无法调用USB.funNew2();// 通过接口调用静态方法}
}

1.3 总结

通过代码演示发现
  • jdk8之后接口中被default的方法不是抽象方法,可以被重写,也可以不重写,不强制
  • 且方法还可以被static修饰,不能被重写,调用,只能通过接口调用
作用
  • 默认方法允许在不破坏现有实现的情况下向接口添加新功能。
  • 可以在不改变现有用户代码的情况下扩展接口。
  • 促进了API的演进,同时保持了向后的兼容性。

二、Lambda表达式[重点]

Lambda是匿名内部类的简化

Lambda 允许把函数(方法)作为一个方法的参数(函数作为参数传递到方法中)。


其实就是简化了匿名内部类的写法,更准确的说是对接口方法的重写的简化

2.1 将匿名内部类写法改写为lambda写法

使用lambda改写创建线程的方式

    public static void main(String[] args) {new Thread(new Runnable( ) {@Overridepublic void run() {for (int i = 0; i < 10001; i++) {System.out.println("正常实现Runnable完成线程" + i);}}}).start( );// 改成lambda形式// lambda是简化了匿名内部类,只剩下关于方法的参数列表和方法体// () -> {}new Thread(() -> {for (int i = 0; i < 10001; i++) {System.out.println("lambda完成线程"+i);}}).start( );// lambda是将方法当参数传递给另外一个方法}
}

2.2 语法特点

能够写成lambda形式的的前提
  1. 方法得有参数
  2. 参数的必须是接口
  3. 接口中的方法有且只能有一个!!!
语法特征

(参数) -> {执行语句}
或者
参数 -> 执行语句

  • 参数圆括号,当参数是一个的时候,圆括号可加可不加

    • (x) -> System.out.println(x)
    • x -> System.out.println(x)
  • 参数圆括号,当参数是多个的时候,圆括号必须加

    • (x,y) -> System.out.println(x+y)
  • 参数数据类型可写可不写,编译时会自动推断是什么类型

    • (x,y) -> System.out.println(x+y)
    • (int x,String y) -> System.out.println(x+y)
  • 执行语句的花括号,当且仅当执行语句只有一句时,可以不加花括号

    • new Thread(() -> System.out.println("匿名内部类开启线程")).start();
      
  • 执行语句的花括号,当执行语句不只一句时,必须加花括号

    • new Thread(() -> {int a = 1;a++;System.out.println("lambda开启线程" );}).start();
      
  • 关于返回值

    • 如果方法有返回值,且执行语句只有一行语句时,可以不用写return,直接写值

      test(() -> {return 1;});
      test(() -> 1);// 1就是return1
      
    • 如果代码比较多,又要返回数据,就必须写上return

      test(() -> {int a = 1;a++;return a;
      });
      
代码演示
ppublic class lambdaTest {/*1. **方法得有参数**2. **参数的必须是接口**3. **接口中的方法有且只能有一个!!!***/public static void main(String[] args) {// 如果lambda方法体中只有一行代码,{}可以省略show1(() -> System.out.println("无参无返回值"));// 如果lambda方法体中有多行代码,{}不能省略show1(() -> {System.out.println("无参无返回值1");System.out.println("无参无返回值2");System.out.println("无参无返回值3");});/** 有参数列表时,参数类型可以省略*/// 只有一个参数,()可以省略show2(b1 -> System.out.println(b1 * 10));// 参数数量>1,()不可以省略show3((c1,c2)->System.out.println(c1 + c2));// 有返回值,但是只有一行代码,{}可以省略,return也可以省略,-> 跟的就是返回值show4(d -> d);}//接口IA为参数,IA只有一个方法static void show1(IA ia){ia.a();}//接口IB为参数,IB只有一个方法static void show2(IB ib){ib.b(1);}//接口IC为参数,IC只有一个方法static void show3(IC ic){ic.c(1,2);}//接口ID为参数,ID只有一个方法static void show4(ID id){id.d(10);}
}
// 接口:IA只有一个无参无返回值方法
interface IA{void a();  //无参无返回值
}// 接口:IA只有两个个无参无返回值方法
interface IC{void c(int c1,int c2);  //参无返回值
}// 接口:IA只有一个无参无返回值方法
interface IB{void b(int b);  //无参无返回值
}// 接口:IA只有一个无参无返回值方法
interface ID{int d(int a);  //无参无返回值
}
深入理解lambda

为什么lambda要设计成,将方法(功能) 当参数传递给方法

  • 有了lambda,方法的功能不再局限,方法具体如何,要看看lambda功能如何
public class Demo3 {public static void main(String[] args) {double add = add(1, 2);System.out.println("add = " + add);double yunsuan = yunsuan((x, y) -> x / y, 1, 2);System.out.println("yunsuan = " + yunsuan);}/*** 已经的方法,参数列表是普通变量* 方法功能已经定好,唯一变化的是参数的值* 例如,这个add方法,是做两数相加,只能相加* 唯一能变的是,加的数不一样* --------------------------* 那如果,我想传入两个参数,让其相除返回结果?让其相乘返回结果?* 就需要重新设计方法*/public static double add(int a,int b){return a + b;}/*** 有了lambda之后,方法的执行功能就不再固定* 如何运行,要看调用时,传入的lambda是如何运行的*/public static double yunsuan(IE e,int a,int b){return e.jisuan(a, b);}}
interface IE {double jisuan(int a,int b);
}

2.3 总结

  • 其实 () -> {}
    • ()里面放的是重写方法的参数
    • {}里面放的是重写方法的方法体
    • 上面各种写法只是在特定情况下的简写,没有特定条件是没法简写的,就要按部就班来
  • lambda就是简化了匿名内部类的写法
  • lambda其实就是接口方法的重写
  • lambda的参数和返回值是根据接口方法决定的

三、函数式接口

3.1 概念

什么是函数式接口

接口中只有一个抽象方法时,该接口就是函数式接口.

Java提供了一个注解可以校验接口是否是函数式接口

@FunctionalInterface

Java中提供了几个特别常用的函数式接口

  • Supplier 供应,即返回一个数据 (无参有返回值的方法)
  • Consumer 消费,即给其传入数据做运算 (有参无返回值的方法)
  • Function 函数,传入2个参数,用于转换数据的 (有参有返回值的方法)
  • Predicate 判断,返回时boolean (有参,返回值是boolean)

四个典型的函数式接口

3.2 Supplier

  • Supplier.java源码
@FunctionalInterface
public interface Supplier<T> {/*** Gets a result.** @return a result*/T get();
}
// 该接口用来返回一个数据,所以叫供应商
// 其实就是无参数有返回值的接口,用的时候就是无参有返回值的lambda

练习,设计方法,通过Supplier接口,获得字符串的长度

		/** Supplier接口 ---顾名思义:供应,提高*  提供的方法--- T get();*  不需传入参数,就有返回值*///利用Supplier接口,实现获得字符串长度功能int i = get(() -> "java".length());System.out.println("i = " + i);// i = 4//参数为Supplier接口的方法public static int get(Supplier<Integer> supplier){return supplier.get();}

3.3 Consumer

JDK中Consumer.java源码

@FunctionalInterface
public interface Consumer<T> {/*** Performs this operation on the given argument.* 给传入一个值,对该值进行操作* @param t the input argument*/void accept(T t);
}
// 其实就是有参数无返回值的接口,用的时候就是有参无返回值的lambda

练习:设计方法,传入字符串,将字符串全部转大写,后输出

 		/** Consumer接口 ---顾名思义:消费,消耗*  提供的方法--- void accept(T t);*  需传入参数,无返回值*///利用Consumer接口,实现字符串转大写功能String s = "java";accept(c -> System.out.println(c.toUpperCase()),s);// JAVA//参数为Consumer接口的方法public static void accept(Consumer<String> consumer,String s){consumer.accept(s);}

3.4 Function

JDK中Function.java源码

@FunctionalInterface
public interface Function<T, R> {/*** Applies this function to the given argument.** @param t the function argument* @return the function result*/R apply(T t);
}
// 该接口用于,转换数据
// 其实就是有参数有返回值的接口,用的时候就是有参有返回值的lambda

利用Function,实现字符串数字转为整形数字功能

	 	/** Function<T, R>接口 ---顾名思义:函数,功能*  提供的方法--- R apply(T t);*  将T转换乘R类型 ,即转换数据*///利用Function,实现字符串数字转为整形数字功能String s2 = "111";Integer apply = apply(f -> Integer.parseInt(f), s2);System.out.println("apply = " + apply);// apply = 111//参数为Function接口的方法public static Integer apply(Function<String,Integer> function,String s){return function.apply(s);}

3.5 Predicate

JDK中Predicate.java源码

@FunctionalInterface
public interface Predicate<T> {/*** Evaluates this predicate on the given argument.** @param t the input argument* @return {@code true} if the input argument matches the predicate,* otherwise {@code false}*/boolean test(T t);
}

判断数据是否是偶数

   /** Predicate接口 ---顾名思义:判断,断定*  提供的方法--- boolean test(T t);*  提供判断方法*///利用Predicate接口,实现判断是否时偶数功能int i1 = 2;boolean b = predicate(a -> a % 2 == 0, i1);System.out.println("b = " + b); // b = true//参数为Predicate接口的方法public static boolean predicate(Predicate<Integer> predicate,Integer integer){return predicate.test(integer);}

3.6 总结

  • Supplier接口的方法一般用于 获得数据
  • Consumer接口的方法 一般用于 处理数据
  • Function接口的方法一般用于 转换数据
  • Predicate接口的方法一般用于 判断数据

思维导图

在这里插入图片描述


最后

如果感觉有收获的话,点个赞 👍🏻 吧。
❤️❤️❤️本人菜鸟修行期,如有错误,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ISO17025认证是什么?怎么做?

ISO17025认证是一种国际通用的实验室质量管理体系认证&#xff0c;其目标是确保实验室的技术能力、管理水平以及测试结果的可靠性和准确性达到国际认可的标准。该认证由国际标准化组织&#xff08;ISO&#xff09;和国际电工委员会&#xff08;IEC&#xff09;联合发布&#xf…

pytorch神经网络训练(AlexNet)

导包 import osimport torchimport torch.nn as nnimport torch.optim as optimfrom torch.utils.data import Dataset, DataLoaderfrom PIL import Imagefrom torchvision import models, transforms 定义自定义图像数据集 class CustomImageDataset(Dataset): 定义一个自…

美丽的拉萨,神奇的布达拉宫

原文链接&#xff1a;美丽的拉萨&#xff0c;神奇的布达拉宫 2022年11月30日&#xff0c;可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT-3.5&#xff0c;将人工智能的发展推向了一个新的高度。2023年11月7日&#xff0c;OpenAI首届…

TcpClient 服务器、客户端连接

TcpClient 服务器 TcpListener 搭建tcp服务器的类&#xff0c;基于socket套接字通信的 1 创建服务器对象 TcpListener server new TcpListener(IPAddress.Parse("127.0.0.1"), 3000); 2 开启服务器 设置最大连接数 server.Start(1000); 3 接收客户端的链接,只能…

Android帧绘制流程深度解析 (二)

书接上回&#xff1a;Android帧绘制流程深度解析 &#xff08;一&#xff09; 5、 dispatchVsync&#xff1a; 在请求Vsync以后&#xff0c;choreographer会等待Vsync的到来&#xff0c;在Vsync信号到来后&#xff0c;会触发dispatchVsync函数&#xff0c;从而调用onVsync方法…

手机和模拟器的 Frida 环境配置

目录 一、配置 JDK 和 android 环境 二、连接设备和查看权限 1、连接设备 2、查看手机权限 三、手机配置 Frida 1、frida-server下载 2、验证 四、模拟器配置 Frida 1、下载模拟器并调节成手机版&#xff1a; 2、连接并查看架构 3、配置并开启 x86 的 frida-serve…

中文大数据训练的数据集

在训练中文大模型时&#xff0c;选择合适的数据集至关重要。以下是一些常用于中文大数据训练的数据集&#xff1a; 1. 新闻数据集 新闻数据集通常涵盖广泛的领域&#xff0c;包括时事、财经、体育、科技等&#xff0c;具有实时性和高质量的特点。 SogouCA&#xff1a;搜狗公…

shell脚本循环

循环&#xff1a; 循环是一种重复执行一段代码的结构。只要满足循环的条件会一直执行此代码。 组成部分&#xff1a;循环条件、循环体 **循环条件&#xff1a;**在一定范围之内&#xff0c;按照指定的次数来执行循环。 **循环体&#xff1a;**在指定的次数内&#xff0c;执行…

Phybers:脑纤维束分析软件包

摘要 本研究提供了一个用于分析脑纤维束数据的Python库(Phybers)。纤维束数据集包含由表示主要白质通路的3D点组成的流线(也称为纤维束)。目前已经提出了一些算法来分析这些数据&#xff0c;包括聚类、分割和可视化方法。由于流线的几何复杂性、文件格式和数据集的大小(可能包…

深度学习 - RNN训练过程推演

1. 数据准备 字符序列 “hello” 转换为 one-hot 编码表示&#xff1a; 输入: [‘h’, ‘e’, ‘l’, ‘l’]输出: [‘e’, ‘l’, ‘l’, ‘o’] 2. 初始化参数 假设我们使用一个单层的 RNN&#xff0c;隐藏层大小为2。初始参数如下&#xff1a; W x h ( 0.1 0.2 0.3 0.4…

HTML静态网页成品作业(HTML+CSS)—— 环保主题介绍网页(5个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有5个页面。 二、作品演示 三、代…

多层tablayout+ViewPager,NestedScrollView+ViewPager+RecyclerView,嵌套吸顶滑动冲突

先看实现的UI效果 其实就是仿BOSS的页面效果&#xff0c;第二层tab下的viewpager滑到最右边再右滑&#xff0c;就操作第一层viewpager滑动。页面上滑时把第一层tab和vp里的banner都推出界面&#xff0c;让第二层tab吸顶。 滑上去第二个tab块卡在顶部&#xff0c;如图 我混乱…

React 渲染函数render、初始化函数、更新函数运行了两次,原因为何,如何解决? React.StrictMode

文章目录 Intro官网解释解决另一篇官网文章——初始化函数或更新函数运行了两次 Intro 我在用 react 写一个 demo &#xff0c;当我在某个自定义组件的 return 语句之前加上一句log之后&#xff0c;发现&#xff1a;每次页面重新渲染&#xff0c;该行日志都打印了两次&#xf…

HOW - 锚点(Anchor)导航

目录 创建锚点导航目录结构页面内容 说明样式和体验优化关键点总结 在Web开发中&#xff0c;锚点&#xff08;Anchor&#xff09;通常用于创建页面内的导航链接&#xff0c;使用户可以点击链接跳转到页面的特定部分。这通常通过HTML中的id属性和链接中的哈希片段实现。 以下是…

vue-loader

Vue Loader 是一个 webpack 的 loader&#xff0c;它允许你以一种名为单文件组件 (SFCs)的格式撰写 Vue 组件 起步 安装 npm install vue --save npm install webpack webpack-cli style-loader css-loader html-webpack-plugin vue-loader vue-template-compiler webpack…

论文阅读Rolling-Unet,卷积结合MLP的图像分割模型

这篇论文提出了一种新的医学图像分割网络Rolling-Unet&#xff0c;目的是在不用Transformer的前提下&#xff0c;能同时有效提取局部特征和长距离依赖性,从而在性能和计算成本之间找到良好的平衡点。 论文地址&#xff1a;https://ojs.aaai.org/index.php/AAAI/article/view/2…

使用nmcli命令创建、删除bond

前言 在之前的文章中&#xff0c;描述的创建bond的方式&#xff0c;是使用配置文件的方式&#xff0c;在创建bond的时候创建一个对应的配置文件&#xff0c;修改、删除都操作此配置文件&#xff0c;这种方式实现bond没有问题&#xff0c;但是对于某些系统下&#xff0c;bond灵…

用链表实现的C语言队列

一、队列概述 在数据结构中&#xff0c;队列是一种先进先出&#xff08;FIFO&#xff09;的线性表。它在许多应用场景中非常有用&#xff0c;例如任务调度、进程管理、资源管理等。队列是一种重要的数据结构&#xff0c;其主要特点是先进先出&#xff08;FIFO, First In First …

618购物狂欢节有哪些数码好物值得抢购?年终必备神器清单大揭秘!

一年一度的“618年中大促”即将拉开帷幕&#xff0c;大家是否已经挑选好了心仪的宝贝呢&#xff1f;那些平时心仪已久的商品&#xff0c;是否总期待着在价格最优惠时收入囊中&#xff1f;毫无疑问&#xff0c;618就是这样一个绝佳的时机&#xff0c;因为各大电商平台都会纷纷推…

python datetime time timedelta

datetime 参考&#xff1a;https://blog.csdn.net/lovedingd/article/details/134929553 time timedelta 参考&#xff1a;https://geek-docs.com/python/python-ask-answer/981_python_formatting_timedelta_objects.html timedelta 是 Python 中的一个类&#xff0c;用于…