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{
    @Override
    public void fun1() {
        System.out.println("重写旧方法");
    }

    @Override
    public 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( ) {
            @Override
            public 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接口的方法一般用于 判断数据

思维导图

在这里插入图片描述


最后

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

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

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

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

相关文章

FastAPI操作关系型数据库

FastAPI可以和任何数据库和任意样式的库配合使用&#xff0c;这里看一下使用SQLAlchemy的示例。下面的示例很容易的调整为PostgreSQL&#xff0c;MySQL&#xff0c;SQLite&#xff0c;Oracle等。当前示例中我们使用SQLite ORM对象关系映射 FastAPI可以与任何数据库在任何样式…

Vulnhub-DC-8

靶机IP:192.168.20.143 kaliIP:192.168.20.128 网络有问题的可以看下搭建Vulnhub靶机网络问题(获取不到IP) 信息收集 用nmap和wappalyzer收集下信息 发现是Drupal 7网站 dirsearch扫下目录 ┌──(root㉿kali)-[/home/kali/Desktop] └─# dirsearch -u http://192.168.20…

【Spring EL<二>✈️✈️ 】SL 表达式结合 AOP 注解实现鉴权

目录 &#x1f37b;前言 &#x1f378;一、鉴权&#xff08;Authorization&#xff09; &#x1f37a;二、功能实现 2.1 环境准备 2.2 代码实现 2.3 测试接口 &#x1f379;三、测试功能 3.1 传递 admin 请求 ​ 3.2 传递普通 user 请求 &#x1f37b;四、章末 &a…

eFuse电子保险丝,需要了解的技术干货来啦

热保险丝作为一种基本的电路保护器件&#xff0c;已经成功使用了150多年。热保险丝有效可靠、易用&#xff0c;具有各种不同的数值和版本&#xff0c;能够满足不同的设计目标。然而&#xff0c;对于寻求以极快的速度切断电流的设计人员来说&#xff0c;热保险丝不可避免的缺点就…

t265 jetpack 6 px4 ros2

Ubuntu22.04 realsenseSDK2和ROS2Wrapper安装方法,包含T265版本踩坑问题_ros2 realsense-CSDN博客 210 git clone https://github.com/IntelRealSense/librealsense.git 212 git branch 215 git tag 218 git checkout v2.51.1 219 git branch 265 git clone https://…

法考报名照片审核不通过?原因看过来

法考报名照片审核不通过&#xff1f;原因看过来&#x1f440;

API工具--Apifox和Postman对比(区别)

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

Python 俄罗斯方块小游戏【含Python源码 MX_007期】

系统简介&#xff1a; 俄罗斯方块是一款经典的俄罗斯益智游戏&#xff0c;由苏联工程师阿列克谢帕基特诺夫&#xff08;Alexey Pajitnov&#xff09;于1984年创建。在游戏中&#xff0c;玩家需要操纵不同形状的方块&#xff0c;以水平移动和旋转的方式&#xff0c;使它们在屏幕…

Python学习从0开始——Kaggle时间序列002

Python学习从0开始——Kaggle时间序列002 一、作为特征的时间序列1.串行依赖周期 2.滞后序列和滞后图滞后图选择滞后 3.示例 二、混合模型1.介绍2.组件和残差3.残差混合预测4.设计混合模型5.使用 三、使用机器学习进行预测1.定义预测任务2.为预测准备数据3.多步骤预测策略3.1 M…

Pytorch安装

一、window 下载CUDA Driver nvidia-driver(NVIDIA驱动程序)是操作系统与NVIDIA GPU硬件之间的软件接口。它负责管理GPU硬件的操作、资源分配、性能优化等任务。CUDA依赖于NVIDIA的驱动程序,因为它需要与GPU硬件进行通信以执行并行计算任务。在使用CUDA进行开发时,确保安装了…

Qt多线程之moveToThread()函数

文章目录 一、moveToThread()执行后&#xff0c;当前代码线程没有改变。二、对象执行moveToThread()后&#xff0c;哪些成员加入了子线程1、创建对象时不指定父对象2、对属性对象使用moveToThread加入子线程作用域3、将属性对象的创建放到子线程中执行 三、C内存模型 在使用“继…

基于改进下垂控制的微电网控制研究(matlab)

主要内容 该模型为simulink仿真模型&#xff0c;主要实现的内容如下&#xff1a; 模型比较全面&#xff0c;包括蓄电池、超级电容和光伏发电模块&#xff0c;同时包括阻性负载和冲击负载&#xff0c;能够较好的了解这些模块对于母线电压特性的研究。采用改进的下垂控制策略…

嘉之音真丝彩绘吸音画,把记忆与向往刻进艺术里

那一瞬间定格在记忆中 那一刹那感动到骨髓里 曾经 现在 将来 每一幅画&#xff0c;都是一个故事的开始&#xff0c;一段记忆的延续&#xff0c;它们承载着过去&#xff0c;映照着现在&#xff0c;启迪着未来。在艺术的世界里&#xff0c;每个人都能找到属于自己的那一幅画…

STM32F103ZET6_HAL_CAN

1定义时钟 2定义按键 按键上拉电阻 3开启串口 4打开CAN&#xff08;具体什么意思上一篇讲了&#xff09; 5生成代码 /* USER CODE BEGIN Header */ /********************************************************************************* file : main.c* brief …

HarmonyOS Next 系列之HTTP请求封装和Token持久化存储(四)

系列文章目录 HarmonyOS Next 系列之省市区弹窗选择器实现&#xff08;一&#xff09; HarmonyOS Next 系列之验证码输入组件实现&#xff08;二&#xff09; HarmonyOS Next 系列之底部标签栏TabBar实现&#xff08;三&#xff09; HarmonyOS Next 系列之HTTP请求封装和Token…

2024年6月14日 十二生肖 今日运势

小运播报&#xff1a;2024年6月14日&#xff0c;星期五&#xff0c;农历五月初九 &#xff08;甲辰年庚午月己酉日&#xff09;&#xff0c;法定工作日。今天世界献血日&#xff0c;捐献新鲜血液&#xff0c;挽救更多生命&#xff0c;每位献血者都是英雄&#xff01; 红榜生肖…

云渲染动画:C4D如何正确渲染导出动画?

​C4D是一款功能强大的3D建模、动画和渲染软件&#xff0c;在制作动画时&#xff0c;正确的渲染和导出流程至关重要&#xff0c;以确保动画质量和流畅性。 帧率概念 动画就是一幅幅图片连贯起来&#xff0c;30帧/秒&#xff0c;就是一秒出现30张图片一般国外都是30&#xff0c…

打破数据分析壁垒:SPSS复习必备(一)

一、数据录入与数据获取 1.变量的测量尺度 &#xff08;1&#xff09;定类尺度 顾名思义&#xff0c;是对事物的类别或属性的一种测度&#xff0c;按照事物的某种属性对其进行分类或分组。 该类变量只能计算频数和频率&#xff0c;用表示 &#xff08;2&#xff09;定序尺…

table组件,前端如何使用table组件,打印数组数据,后端传输的数据应该如何打印

一、如何使用table&#xff0c;将数组数据打印出来 后端传来的数据&#xff0c;很大概率是一个List数组&#xff0c;我们必须用一个table组件&#xff0c;来打印这些数据。 table标签的介绍 在HTML中&#xff0c;table是常用组件之一&#xff0c;主要用来打印数组信息。 它的…

yolo-inference多后端+多任务+多算法+多精度模型 框架开发记录(python版)

先贴出github地址&#xff0c;欢迎大家批评指正&#xff1a;https://github.com/taifyang/yolo-inference 不知不觉LZ已经快工作两年了&#xff0c;由于之前的工作内容主要和模型部署相关&#xff0c;想着利用闲暇时间写一些推理方面的经验总结&#xff0c;于是有了这个工程。其…