JDK1.8 新特性(一)【默认方法、静态方法和Lambda表达式】

news2025/1/15 17:36:24

前言 

        今天学习Java8 新特性,主要是之前在学习 Scala、JavaFX 中遇到一些 Lambda 表达式,感觉 lambda 表达式确实很简洁,很有必要学一学。

目录

前言

1、接口的默认方法与静态方法

编写接口

编写接口的实现类

测试

2、Lambda表达式(重点)

2.1、Lambda 表达式规范

2.1.1、函数接口的定义

2.1.2、Java 内置的函数接口 

2.2、Lambda 基础语法

2.2.1、无参方法调用

(1)编写函数接口

(2)使用 lambda 

2.2.2、有参方法调用

(1)编写函数接口

(2)使用 lambda 

2.3、Lambda 的精简写法

2.3.1、无参方法

2.3.2、有参方法

练习

2.4、Lambda 实战

forEach

集合排序


1、接口的默认方法与静态方法

什么是普通方法?

我们可以把 Java 中的方法看成两类:普通方法(有方法体的)和抽象方法(没有方法体的,需要子类去实现的,比如接口、抽象类)。

JDK8 之前,Java 中接口 Interface 之中可以定义变量和方法:

  • 变量 必须是 public、static、final 的
  • 方法 必须是 public、abstract 的

而且这些修饰符都是默认的,也就是不需要我们写。

从JDK8 开始 支持使用 static 和 default 来修饰方法可以写方法体不需要子类重写被 static 和 default修饰的方法

接口中定义的默认方法只有子类对象才能调用,而接口中定义的静态方法只有接口类才能调用。

编写接口

public interface JDK8Interface {
    /*
     * 默认就是 public abstract 的,不需要加修饰符
    */
    void add();
    /*
     * JDK8 提供 默认的方法
     */
    default void get(){
        System.out.println("get");
    }

    /*
     * JDK8 提供的静态方法 只能通过 接口名.方法名来 调用
     */
    static void del(){
        System.out.println("del");
    }
}

编写接口的实现类

public class JDK8InterfaceImpl implements JDK8Interface {

    @Override
    public void add() {
        System.out.println("add");
    }
    
}

测试

public class Test01 {
    public static void main(String[] args) {
        JDK8InterfaceImpl jdk8Interface = new JDK8InterfaceImpl();
        jdk8Interface.add();
        jdk8Interface.get();
        JDK8Interface.del();    
    }
}

我们可以得到这样一个结论:接口中定义的默认方法只有子类对象才能调用,而接口中定义的静态方法只有接口类才能调用。

2、Lambda表达式(重点)

什么是 Lambda 表达式?

Lanmbda 表达式是一个匿名函数,即没有函数名的函数,基于数学中的 λ 而得名。

优点:简化匿名内部类的调用,减少代码量。

缺点:不好调试

编写接口:

public interface OrderService {
    void get();
}

 测试:

public class Test02 {
    public static void main(String[] args) {

        // 1. 通过匿名内部类创建一个实现OrderService接口的子类
        OrderService service = new OrderService() {
            @Override
            public void get() {
                System.out.println("get");
            }
        };
        service.get();

        // 2. lambda 表达式  括号代表参数列表
        ((OrderService) ()-> System.out.println("get")).get();

        // 3. 同样是lambda表达式
        new Thread(()-> System.out.println("get")).start();

    }
}

注意:这里的接口只能有一个抽象方法!

2.1、Lambda 表达式规范

2.1.1、函数接口的定义

Java 中使用 Lambda 表达式依赖于函数接口。我们在 new 一个对象或者使用一个方法,需要传入的参数是接口类型时,可以使用该 接口的实现类,也可以直接构造一个匿名内部类(这里我们就可以通过 lambda 表达式来简化代码,提高开发效率,主要是看起来是真的舒服)。

  • 在接口当中只允许存在一个抽象方法。
  • 允许使用 default 和 static 修饰的方法。
  • 使用注解 @FunctionalInterface 来标记该接口为函数接口(接口中只包含一个方法的叫做函数接口),我们可以发现,如果接口中出现了超过1个的抽象方法代码就会爆红。
  • 可以定义 Object 类中的方法

下面是我自定义的一个函数接口。

/**
 * 函数接口 只允许包含一个抽象方法
 * 4. 使用注解 @FunctionalInterface 来标注着是一个函数接口
 */
@FunctionalInterface
public interface MyFunctionInterface {
    // 1. 只允许存在一个方法
    void get();

    // 2. 允许存在 default 和 static 修饰的方法
    default void add(){
        System.out.println("add");
    }
    static void ss(){
        System.out.println("ss");
    }

    // 3. 可以存在 Object 类中的方法
    String toString();
    boolean equals(Object obj);
    int hashCode();
}

2.1.2、Java 内置的函数接口 

new Thread(new Runnable() {
            @Override
            public void run() {
               // 方法体 
            }
        }).start();

正因为i Runnable 是一个函数接口,所以我们可以这样简写:

new Thread(()->{
          // 方法体  
        }).start();

2.2、Lambda 基础语法

语法:

() -> {}
  • ():参数列表 
  • ->:分隔符
  • {}:方法体

2.2.1、无参方法调用

(1)编写函数接口

@FunctionalInterface
public interface ParamLambdaInterface {
    void get();
}
(2)使用 lambda 
public class Test03 {
    public static void main(String[] args) {
        // 1. 匿名内部类
        new ParamLambdaInterface(){
            @Override
            public void get() {
                System.out.println("get");
            }
        };
        // 2. lambda 表达式
        ParamLambdaInterface pl = () -> {
            System.out.println("get");
        };
        pl.get();

    }
}

 

2.2.2、有参方法调用

(1)编写函数接口
@FunctionalInterface
public interface OrderService {
    void get(String name);
}
(2)使用 lambda 
public class Test04 {
    public static void main(String[] args) {

        // 1. 通过匿名内部类创建一个实现OrderService接口的子类
        OrderService service = new OrderService() {
            @Override
            public void get(String name) {
                System.out.println(name);
            }
        };
        service.get("tom");

        // 2. lambda 表达式 参数类型可以省略
        OrderService od = (name)->{
            System.out.println(name);
        };
        od.get("get");
    
        // 简化
        ((OrderService) System.out::println).get("tom");
    }
}

2.3、Lambda 的精简写法

2.3.1、无参方法

上面 2.2.1 也可以这么写:

// 一行代码的情况下 可以省去花括号
((ParamLambdaInterface) () -> System.out.println("get")).get();

2.3.2、有参方法

2.2.2 可以这么写:

如果参数只有一个可以省去括号

((OrderService) name -> System.out.println(name)).get("get");

练习

定义一个用于计算和的函数接口

@FunctionalInterface
public interface AddInterface {
    int add(int a,int b);
}

测试,求 1 和 2 的和

int result = ((AddInterface) (a, b) -> a + b).add(1, 2);

2.4、Lambda 实战

forEach

定义一个存放姓名的 List :

List<String> list = new ArrayList<>();
        list.add("mike");
        list.add("tom");
        list.add("bob");

使用 List 的 forEach 方法打印所有元素: 

可以看到 forEach 的参数也是一个函数接口,而且只有一个抽象方法 accept。 

    // 1. 普通写法
    list.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });    
    
    // 2. lambda
    list.forEach(name-> System.out.println(name) );

    // 简化
    list.forEach(System.out::println);

将输出结果全部大写输出:

// 将名字转为大写再输出
        list.forEach(name-> System.out.println(name.toUpperCase(Locale.ROOT)));

集合排序

数据准备

public class User {
    private String name;
    private Integer age;

    public User(){}

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

创建一个 User 集合

List<User> list = new ArrayList<>();
        list.add(new User("mike",20));
        list.add(new User("bob",18));
        list.add(new User("tom",25));

使用 lambda 进行排序:

    // 1. 普通写法
    list.sort(new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                return 0;
            }
        });
    // 2. lambda 表达式
    list.sort((user1,user2)-> user1.getAge()-user2.getAge());   // 升序排列
    
    // 输出结果
    list.forEach(System.out::println);

运行结果:

User{name='bob', age=18}
User{name='mike', age=20}
User{name='tom', age=25}

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

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

相关文章

YOLO目标检测——交通标志分类数据集下载分享【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;交通标志识别数据集在自动驾驶、交通安全监控、智能交通系统、驾驶员辅助系统和城市规划等领域都有广泛应用的潜力数据集说明&#xff1a;交通标志分类数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富&#xff0c;含多场景白天黑…

Linux之gdb

gdb就是一个Linux的调试工具&#xff0c;类似与vs里面的调试 可执行程序也有格式&#xff0c;不是简单的二进制堆砌

PyCharm因安装了illuminated Cloud插件导致加载项目失败

打开Pycharm时会有弹窗提示&#xff1a; The license for Illuminated Cloud is invalid or has expired. All Illuminated Cloud features will be disabled. 这个弹窗会导致你加载项目一直失败&#xff0c;close project 也关不掉&#xff0c;我都是用任务管理器杀死进程的…

DevChat全能型AI编程助手,助你“以一敌三卷翻好友”

DevChat全能型AI编程助手&#xff0c;助你“以一敌三卷翻好友” 什么是DevChat&#xff0c;它能帮助我们做什么&#xff1f; DevChat是OpenAI的一个产品&#xff0c;它是一个可以进行编程相关对话的AI。这意味着你可以使用它来解决一些编程上的问题或者获取关于编程的建议。 …

Doris:读取Doris数据的N种方法

目录 1.MySQL Client 2.JDBC 3. 查询计划 4.Spark Doris Connector 5.Flink Doris Connector 1.MySQL Client Doris 采用 MySQL 协议&#xff0c;高度兼容 MySQL 语法&#xff0c;支持标准 SQL&#xff0c;用户可以通过各类客户端工具来访问 Doris。登录到doris服务器后&a…

基于SSM框架的高校试题管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

交换机工作原理

交换机工作原理 交换机功能&#xff1a;端口扩展&#xff08;默认同一网络&#xff09;&#xff0c;如果只是两台设备进行通信&#xff0c;可以直接连接这两台设备而不用交换机&#xff0c;但如果设备较多&#xff0c;设备没有那么多接口&#xff0c;那么这个时候就需要交换机…

智慧水利整体解决方案:PPT全文43页,附下载

关键词&#xff1a;智慧水利发展前景&#xff0c;智慧水利解决方案&#xff0c;智慧水利建设方案&#xff0c;智慧水利平台系统 一、智慧水利建设背景 传统水利系统存在一些问题&#xff1a; 现有基础感知不能满足更高标准的水利管理需求&#xff1b;决策调度支撑能力亟需加强…

ztree结合hmap使用经验分享

项目背景 在建德封控拦截系统&#xff08;Vue3antd2.x&#xff09;为追求更快的地图初始化体验&#xff0c;在尝试了hmap2.5.0版本以及2.6.3版本后&#xff0c;由于这两个版本在现场电脑的初始化速度不够流畅&#xff0c;最终使用的是hmap2.1.3版本。同时由于布控选设备&#…

c语言练习第11周(1~5)

数列 1 1 2 3 5 8 13 21 ... 被称为斐波纳数列。 输入若干个正整数N&#xff0c;输出这个序列的前 N 项的和。 题干数列 1 1 2 3 5 8 13 21 ... 被称为斐波纳数列。 输入若干个正整数N&#xff0c;输出这个序列的前 N 项的和。输入样例3 5 4 1输出样例…

ftp服务器(filezilla服务端软件)下载、安装、使用

下载 通过360软件管家下载 输入filezilla&#xff0c;点击搜索&#xff0c;点击安装 修改安装路径 等待安装完成 配置服务端 启动配置 双击打开&#xff0c;点击软件中间按钮 不用输入密码&#xff0c;因为安装的时候没有设置密码 如果在安装的时候设置了密码&#xff0c;…

可以为一个servlet定义多个servlet-mapping、或url-pattern

在web描述符文件web.xml文件中&#xff0c;可以为同一个servlet定义多个servlet-mapping&#xff1b;也可以在同一个servlet-mapping中&#xff0c;定义多个url-pattern。也就是说&#xff0c;可以把多个地址&#xff08;相对于上下文路径&#xff09;映射到同一个servlet处理。…

基于MATLAB的关节型六轴机械臂轨迹规划仿真

笛卡尔空间下的轨迹规划&#xff0c;分为直线轨迹规划和圆弧轨迹规划&#xff0c;本文为笛卡尔空间下圆弧插值法的matlab仿真分析 目录 1 实验目的 2 实验内容 2.1标准D-H参数法 2.2实验中使用的Matlab函数 3 全部代码 4 仿真结果 1 实验目的 基于机器人学理论知识&…

最全面的软考架构师复习资料(历时2年整理)

一、面向服务的架构 1.请分别用200字以内文字说明什么是面向服务架构&#xff08;SOA&#xff09;以及ESB在SOA的作用与特点 面向服务的体系架构&#xff08;SOA&#xff09;是一种粗粒度、松耦合的服务架构&#xff0c;服务之间通过简单、精确定义接口进行通信。他可以根据需求…

【操作系统】4.2 文件系统

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

[CISCN 2023 西南]do_you_like_read

打开题目&#xff0c;大概是一个购买书籍的网站&#xff0c;有登陆的功能 我们可以先分析下给的源码 在admin.php中会验证是否为admin用户 我们尝试爆破下密码&#xff0c;爆出来为admin123 登陆后发现存在文件上传漏洞 我们分析下源码 存在文件后缀检测&#xff0c;如果为p…

【第四章】软件设计师 之 计算机网络

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 1、七层模型 2、网络技术标准与协议 中介 别…

信捷 XDH 输出点流水灯

本文以XDH 为例&#xff0c;实现输出点流水灯&#xff0c;测试输出点是否正常。 用到了FOR NEXT循环和偏移量实现。 程序下载链接如下&#xff1a; https://download.csdn.net/download/weixin_39926429/88527971

Python的基础语句大全

以下是Python的基础语句大全&#xff1a; 变量定义语句&#xff1a; var_name var_value输出语句&#xff1a; print(var_name)输入语句&#xff1a; var_name input()条件语句&#xff1a; if condition:// do something if condition is True elif condition:// do somethi…

手机地磁传感器与常见问题

在手机中&#xff0c;存在不少传感器&#xff0c;例如光距感&#xff0c;陀螺仪&#xff0c;重力加速度&#xff0c;地磁等。关于各传感器&#xff0c;虽功能作用大家都有所了解&#xff0c;但是在研发设计debug过程中&#xff0c;却总是会遇到很多头疼的问题。关于传感器&…