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

news2025/1/13 17:33:46

目录

  • 一、关于接口的新特性
    • 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接口的方法一般用于 判断数据

思维导图

在这里插入图片描述


最后

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

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

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

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

相关文章

社区疫情管理系统

社区疫情管理系统 java web源码 增删改查 适合新手有导入视频 java项目 ssm疫情防控登记管理社区疫情管理源码jsp项目 技术 ssm 源码➕数据库文件➕eclipse导入视频

基于C#开发web网页管理系统模板流程-打包发布

点击返回目录-> 基于C#开发web网页管理系统模板流程-总集篇-CSDN博客 前言 本系列中&#xff0c;作为开发者我们通过ASP.net Web模板设计网页&#xff0c;网页的任何设计、源代码都是直接可见的&#xff0c;在实际应用开发中&#xff0c;显然这些都是商业、公司机密 通过打包…

Vue基础知识:异步DOM更新是什么?$nextTick是什么?到底应该如何使用。什么是同步?什么是异步?

要先了解异步dom更新是什么就必须先了解&#xff0c;什么是同步&#xff1f;什么是异步&#xff1f; 1.什么是同步&#xff1f;什么是异步&#xff1f; 同步&#xff08;Synchronous&#xff09;&#xff1a; 同步操作是按照代码的顺序执行的&#xff0c;每个操作都必须等待上…

SAP OB52 财务账期月结月底月初开关

公告&#xff1a;周一至周五每日一更&#xff0c;周六日存稿&#xff0c;请您点“关注”和“在看”&#xff0c;后续推送的时候不至于看不到每日更新内容&#xff0c;感谢。 这是一条刮刮乐&#xff0c;按住全部选中&#xff1a;点关注的人最帅最美&#xff0c;欢迎&#xff1…

vue2+echarts:echarts在dialog弹框中不显示的解决方案

重点是open方法里使用$nextTick拿到最新的dom&#xff0c;在里面加载echarts //html <el-button click.stop"getIfStorage"></el-button><el-dialog title"图表数据" :visible.sync"ifStorageShowOpen" open"open()" …

嵌入式系统中判断大小端的方法与实现

第一&#xff1a;大小端基本分析 程序判断计算机是大端的还是小端的&#xff0c;判断的思路是确定一个多字节的值(下面使用的是4字节的整数)&#xff0c;将其写入内存(即赋值给一个变量)&#xff0c;然后用指针取其首地址所对应的字节(即低地址的一个字节)&#xff0c;判断该字…

Photoshop中颜色与色调的调整

Photoshop中颜色与色调的调整 Photoshop中的颜色模式RGB模式灰度模式位图模式索引模式CMYK模式Lab模式 Photoshop中的颜色/色调调整命令颜色/色调调整命令的分类亮度/对比度调整命令色阶命令曲线命令曝光度命令自然饱和度命令色相/饱和度命令色彩平衡命令照片滤镜调整命令通道混…

[leetcode]swap-nodes-in-pairs

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:ListNode* swapPairs(ListNode* head) {ListNode* dummyHead new ListNode(0);dummyHead->next head;ListNode* temp dummyHead;while (temp->next ! nullptr && temp->next->next !…

单链表实现:从理论到代码

✨✨欢迎&#x1f44d;&#x1f44d;点赞☕️☕️收藏✍✍评论 个人主页&#xff1a;秋邱博客 所属栏目&#xff1a;C语言&#xff0c;数据结构 ​ 前言 前面学习了顺序表&#xff0c;顺序表优点&#xff1a; 可以随机访问元素&#xff0c;通过索引能快速定位到元素。存储密…

Python界面编辑器Tkinter布局助手 使用体验

一、发现 我今天在网上搜关于Python Tkinter方面的信息时&#xff0c;发现了Python界面编辑器 Tkinter布局助手 的使用说明。 https://blog.csdn.net/weixin_52777652/article/details/135291731?spm1001.2014.3001.5506 这个编辑器是个开源的项目&#xff0c;个人用户可以…

Python学习笔记7:入门知识(七)

前言 之前说过我更换了新的学习路线&#xff0c;现在是根据官方文档和书籍Python crash course来进行学习的&#xff0c;在目前的学习中&#xff0c;对于之前的知识有一些遗漏&#xff0c;这里进行补充。 学习资料有两个&#xff0c;书籍中文版PDF&#xff0c;关注我私信发送…

Lua实现自定义函数面向对象编程

本文目录 1、引言2、原理3、实例4、层析验证 文章对应视频教程&#xff1a; 暂无&#xff0c;可以关注我的B站账号等待更新。 点击图片或链接访问我的B站主页~~~ 1、引言 在现代软件开发中&#xff0c;面向对象编程&#xff08;OOP&#xff09;已经成为一种广泛使用的编程范式…

nodejs 某音douyin网页端搜索接口及x_bogus、a_bogus(包含完整源码)(2024-06-13)

前言 x_bogus或a_bogus算法大概是对数据、ua、时间戳、浏览器的几个指纹进行计算&#xff0c;拿到一个110位大数组&#xff0c;然后转字符&#xff0c;在头部再添加十二位随机字符&#xff0c;再进行魔改的base64加密。 问&#xff1a;抖音的x_bogus、a_bogus值有什么用&#x…

幸狐RV1106开发板烧录Ubuntu系统与配置SDK,RV1106 LuckFox Pico Max——最新的操作

资料&#xff1a;上手教程 | LUCKFOX WIKI 以及SDK内的文档资料 开发板型号&#xff1a;RV1106 LuckFox Pico Max 烧录系统&#xff1a; Ubuntu 虚拟机系统&#xff1a;Ubuntu 20.04&&Ubuntu22.04 PC系统&#xff1a;win11 占用空间&#xff1a;大概15G 本文主要记…

idea有这个类却报红,无法用快捷键找到

idea有这个类却报红&#xff0c;无法用快捷键找到&#xff0c;但是项目启动却没有任何问题&#xff0c;严重影响到了开发效率&#xff0c;关idea 重新打开没有用。 找了一圈&#xff0c;办法如下&#xff1a; 1、点击左上角的 File—>Invalidate Caches/Restar 2、点击 In…

【Linux】进程控制3——进程程序替换

一&#xff0c;前言 创建子进程的目的之一就是为了代劳父进程执行父进程的部分代码&#xff0c;也就是说本质上来说父子进程都是执行的同一个代码段的数据&#xff0c;在子进程修改数据的时候进行写时拷贝修改数据段的部分数据。 但是还有一个目的——将子进程在运行时指向一个…

Python私教张大鹏 Vue3整合AntDesignVue之DatePicker 日期选择框

案例&#xff1a;选择日期 <script setup> import {ref} from "vue";const date ref(null) </script> <template><div class"p-8 bg-indigo-50 text-center"><a-date-picker v-model:value"date"/><a-divide…

visio绘制直线

1、右键打开绘图工具 2、选择线条 3、画直线、画横线

【推荐算法的评估与调试】离线评估+在线A/B Test

文章目录 1、离线评估1.1、评估排序算法1.1.1、AUC和GAUC1.1.2、NDCG 1.2、评估召回算法1.2.1、Precision&Recall1.2.2、MAP1.2.3、Hit Rate1.2.4、持续评估 2、在线评估2.1、线上&#xff1a;流量划分2.1.1、根据User ID划分流量2.1.2、分层重叠划分流量2.1.3、A/A实验的重…

最新下载:Paragon NTFS for Mac 15【软件附加安装教程】

NTFS For Mac 15是首个支持Mac上读写NTFS外置存储设备解决方案 &#xff0c;解决mac不能读写外置让您更加简单直观的在Mac机上随意对NTFS文件修改、删除等操作。 安 装 包 获 取 地 址&#xff1a; Paragon Ntfs For Mac 15版&#xff1a;​​https://souurl.cn/mqM9C6​​ 软…