Java 1.8新特性

news2024/11/17 5:36:39

接口的默认方法

Java 8允许给接口添加一个非抽象的方法实现,只需要使用default关键字即可,这个特征又叫做扩展方法

interface Formula {
	double calculate(int a);

	default double sqrt(int a) {
		return Math.sqrt(a);
	}
}

Formula接口在拥有calculate方法之外同时还定义了sqrt方法,实现了Formula接口的子类只需要实现一个calculate方法,默认方法sqrt将在子类上可以直接使用


Lambda表达式

从Java 8出现以来lambda是最重要的特性之一,它可以用简洁流畅的代码完成一个功能。 很长一段时间Java被吐槽是冗余和缺乏函数式编程能力的语言,随着函数式编程的流行Java 8种也引入了这种编程风格
可以取代大部分的匿名内部类,写出更优雅的Java代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构
JDK也提供了大量的内置函数式接口供使用,使得Lambda表达式的运用更加方便、高效

什么是Lambda?

lambda表达式是一段可以传递的代码,核心思想是将面向对象中的传递数据变成传递行为

Lambda的作用?

所有的Lambda的类型都是一个接口,而Lambda表达式本身,也就是“那段代码”,需要是这个接口的实现
Lambda表达式本身就是一个接口的实现

语法

()  ->  {}
语法字符描述
()用来描述参数列表
->为 lambda运算符,读作(goes to)
{}用来描述方法体

使用Lambda对接口的要求

虽然使用Lambda表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以使用Lambda表达式来实现。Lambda规定接口中只能有一个需要被实现的方法,也就是只有一个抽象方法;不是规定接口中只能有一个方法,被default修饰的方法会有默认实现,不是必须被实现的方法,所以不影响Lambda表达式的使用

函数式接口

Lambda表达式是如何在Java的类型系统中表示的呢?

每一个Lambda表达式都对应一个类型,通常是接口类型。而“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的Lambda表达式都会被匹配到这个抽象方法。因为默认方法不算抽象方法,所以也可以给函数式接口添加默认方法。

@FunctionalInterface
可以将Lambda表达式当作任意只包含一个抽象方法的接口类型,确保接口一定达到这个要求,只需要给接口添加@FunctionalInterface注解,@FunctionalInterface修饰函数式接口,要求接口中的抽象方法只有一个,编译器如果发现标注了这个注解的接口有多于一个抽象方法的时候会报错的

@FunctionalInterface
interface Converter<F, T> {
	T convert(F from);
}

Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Integer converted = converter.convert("123");
System.out.println(converted);    // 123

需要注意如果@FunctionalInterface如果没有指定,上面的代码也是对的,因为它只有一个需要实现的抽象方法

Lambda作用域

在Lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似。可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量

Lambda访问局部变量

可以直接在Lambda表达式中访问外层的局部变量

final int num = 1;
Converter<Integer, String> stringConverter = (from) -> String.valueOf(from + num);
stringConverter.convert(2);     // 3

但是和匿名对象不同的是,这里的变量num可以不用声明为final,该代码同样正确

int num = 1;
Converter<Integer, String> stringConverter = (from) -> String.valueOf(from + num);
stringConverter.convert(2);     // 3

不过这里的num必须不可被后面的代码修改(即隐性的具有final的语义),例如下面的就无法编译:

int num = 1;
Converter<Integer, String> stringConverter =
        (from) -> String.valueOf(from + num);
num = 3;

在lambda表达式中试图修改num同样是不允许的

Lambda访问对象字段与静态变量

和本地变量不同的是,Lambda对于实例字段、静态变量是即可读又可写。该行为和匿名对象是一致的

class Lambda4 {
    static int outerStaticNum;
    int outerNum;

    void testScopes() {
        Converter<Integer, String> stringConverter1 = (from) -> {
            outerNum = 23;
            return String.valueOf(from);
        };

        Converter<Integer, String> stringConverter2 = (from) -> {
            outerStaticNum = 72;
            return String.valueOf(from);
  **加粗样式**      };
    }
}

无法访问接口的默认方法

Lambda表达式中是无法访问到接口的默认方法,将无法编译
JDK 1.8 API包含了很多内建的函数式接口,在老Java中常用到的比如Comparator或者Runnable接口,这些接口都增加了@FunctionalInterface注解以便能用在Lambda上

匿名内部类

Runnable r = new Runnable() {
    @Override
    public void run() {  //实现函数化接口的抽象方法run
        System.out.println("do something.");      
    }
};

与在实现类中实现抽象方法相似,实现后可以直接runnable.run()调用函数化接口->只有一个抽象方法

Lambda表达式实现

Runnable runnable=( )->{   //run方法的表达式  ( )是方法参数,没有就空着
  System.out.println("do something.");  
};

匿名内部类

匿名内部类也就是没有名字的内部类,正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写

使用匿名内部类还有个前提条件:必须继承一个父类实现一个接口

不具有抽象和静态属性。并且不能派生出子类
匿名内部类只能访问外部的静态变量和final修饰的常量
对于实例字段、静态变量是即可读又可写|实例字段:必须先由其所在的类构造一个实例出来。对象.实例字段
作用:内部类通过该访问路径可以进行内部类内部和外部的数据交互,一般与final结合使用比较多

new Runnable(){}其实不是实例化Runnable接口来的,实际上一种内部类的一种简写
①首先构造了一个“implements Runnable”的无名local内部类(方法内的内部类)
②然后构造了这个无名local内部类的一个实例
③然后用Runnable来表示这个无名local内部类的type(OO多态)

package com.cph.Thread;

public class Text2 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
         Runnable runnable=new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("i am new Runnable(){xxx}");
            }
        };
        Thread thread=new Thread(runnable);
        thread.start();
    }
}

上面这段代码编译后你会看到其实是编译了两个类来的
在这里插入图片描述

其中Text2$1就是无名local内部内类,这个也就很好地解释了为什么在main()方法中new Runnable(){xxx}里面的调用main()方法中的变量的时候要用final关键字来修饰。 上面只是借助new Runnable(){xxx}特例来说明接口在方法中new的机制,对其他接口同理可得

匿名内部类(Anonymous Inner Class),在创建实例的同时给出类的定义,所有这些在一个表达式中完成


方法与构造函数引用

Java 8允许使用“ :: ”关键字来传递方法或者构造函数引用

如何引用一个静态方法,也可以引用一个对象的方法

Converter<String, Integer> converter = Integer::valueOf;
Integer converted = converter.convert("123");
System.out.println(converted);   // 123

converter = something::startsWith;
String converted = converter.convert("Java");
System.out.println(converted);    // "J"

构造函数是如何使用“ :: ”关键字来引用

首先定义一个包含多个构造函数的简单类

class Person {
    String firstName;
    String lastName;
    
    Person() {}
    
    Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

接下来指定一个用来创建Person对象的对象工厂接口

interface PersonFactory<P extends Person> {
    P create(String firstName, String lastName);
}

这里使用构造函数引用来将他们关联起来,而不是实现一个完整的工厂

PersonFactory<Person> personFactory = Person::new;
Person person = personFactory.create("Peter", "Parker");

只需要使用Person::new来获取Person类构造函数的引用,Java编译器会自动根据PersonFactory.create方法的签名来选择合适的构造函数





上一篇:Java注解                        下一篇:Java函数式编程




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

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

相关文章

【Linux初阶】进程的相关概念 | 进程管理 查看进程 获取进程标识符 fork进程创建

&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f; &#x1f36d;&#x1f36d;系列专栏&#xff1a;【Linux初阶】 ✒️✒️本篇内容&#xff1a;进程的概念&#xff0c;进程管理初识&#xff08;描述、管理进程&#xff09;&#xff0c;查看进程的基础方法…

【Nav2】ROS2 Eloquent中使用robot_state_publisher发布松灵Scout mini的urdf

【背景】 本来打算把ROS1版本的松灵Scout mini 模型描述文件直接移植到ROS2的工作空间里去&#xff0c;用robot_state_publisher加载出来&#xff0c;结果行不通&#xff1b;于是找到了ROS2版本的Scout mini 模型描述&#xff0c;结果因为我用的是 Eloquent 版本&#xff0c;而…

MobTech MobPush|A/B测试提升运营决策

在实际推送过程中&#xff0c;我们常常有这样的困惑&#xff1a; 我们如何确定哪种推送内容更能吸引用户&#xff1f; 我们如何衡量推送效果的提升程度&#xff1f; 我们如何优化推送方案&#xff0c;实现更高的ROI&#xff1f; 为了解决这些困惑&#xff0c;我们需要一种科…

碳中和成“必答题”,宁德时代创造产业“零碳”新维度

文 | 智能相对论 作者 | leo陈 2021年&#xff0c;麻省理工学院的教授索尔格里菲斯出版了《零碳未来》一书&#xff0c;这本著作总结了数十年的研究经验和数据&#xff0c;紧迫地提出&#xff0c;我们需要可以利用现有技术和资源快速应对气候变化的“零碳行动方案”。 既要保…

Netty时间轮源码解析

Netty主要应用用于网络通信&#xff0c;Netty还有一个非常重要的应用领域&#xff0c;即时通信系统IM, 在IM聊天系统中&#xff0c;有成千上万条条链路&#xff0c; Netty是如何管理这些链路的呢 &#xff1f; Netty还有一套自带的心跳检测机制&#xff0c;这套检测机制的原理是…

HCIP-7.0华为交换机技术基础学习

交换机基础 1、交换机工作原理1.1、VLAN虚拟局域网1.1.1、VLAN帧格式1.1.2、VLAN的划分方式&#xff1a;1.1.3、PVID1.1.4、Access端口类型1.1.5、Trunk端口类型1.1.6、Hybird端口类型 1.2、MUX VLAN应用场景和原理1.2.1、MUX VLAN原理1.2.2、MUX VLAN配置 1、交换机工作原理 …

软件测试—用例篇(上)

软件测试—用例篇 &#x1f50e;测试用例的概念&#x1f50e;测试用例的好处&#x1f50e;测试用例的设计方法&#x1f338;基于需求的设计方法&#x1f338;等价类划分法&#x1f338;边界值分析法&#x1f338;判定表 &#x1f50e;结尾 &#x1f50e;测试用例的概念 为了实…

【Python】如何用pyth做游戏脚本(太简单了吧)

文章目录 前言一、开发前景二、开发流程3.1、获取窗口句柄&#xff0c;把窗口置顶3. 2、截取游戏界面&#xff0c;分割图标&#xff0c;图片比较 二、程序核心-图标连接算法&#xff08;路径寻找&#xff09;四、开发总结五、源码总结 前言 简述&#xff1a;本文将以4399小游戏…

使用@Import注解给容器中快速导入一个组件

注册bean的方式 向Spring容器中注册bean通常有以下几种方式&#xff1a; 包扫描给组件标注注解&#xff08;Controller、Servcie、Repository、Component&#xff09;&#xff0c;但这种方式比较有局限性&#xff0c;局限于我们自己写的类Bean注解&#xff0c;通常用于导入第…

软测如果这么学,培训班都得倒闭,直接省去上万元的学费

俗话说外行看热闹&#xff0c;内行看门道。 写这篇文章&#xff0c;是希望把我的一些我认为是非常有价值的经验总结出来&#xff0c;能够帮助刚做测试不久的新同学&#xff0c;或者是测试经验丰富的老同学以共享。 希望我们可爱的新同学&#xff0c;准备要在测试领域耕耘的伙…

Git推出大文件储存工具Git LFS,但它真的好用吗?

Git LFS&#xff08;全称为Git Large File Storage&#xff0c;Git大文件存储&#xff09;被许多团队用来管理和存储大文件。本篇文章将解释Git LFS是什么&#xff0c;它的功能和使用场景&#xff0c;以及它究竟是不是管理大文件的最佳版本控制工具。 什么是Git LFS&#xff0…

共治、共建、共享!龙蜥社区第 16 次运营委员会会议顺利召开!

4 月 14 日&#xff0c;龙蜥社区在凝思软件召开了第 16 次运营委员会会议&#xff0c;本次会议由统信软件运营委员会委员崔开主持。来自阿里云、红旗软件、海光、Intel、联通软研院、浪潮信息、凝思软件、普华基础软件、统信软件、万里红、新华三、中科方德等理事单位的 23 位委…

第一章 Go环境搭建

前言 Golang是一种比较新颖的编程语言&#xff0c;其强大的功能以及底层的强大支撑快速的成为了编程语言的佼佼者&#xff0c;使其备受欢迎。 1、Go的安装与配置 如果你有一定的开发经验或者学习知识肯定知道&#xff0c;如何语言的开发都需要进行环境的配置与相关资源的安装…

12. 图的进阶

12. 图的进阶 12.1 有向图 在实际生活中&#xff0c;很多应用相关的图都是有方向性的&#xff0c;最直观的就是网络&#xff0c;可以从A页面通过链接跳转到B页面&#xff0c;那么a和b连接的方向是a->b,但不能说是b->a,此时我们就需要使用有向图来解决这一类问题&#x…

8 年后端开发,API 设计的学习方法分享

笔者目前在参与一个开源项目&#xff0c;平时接触多的也是 API 相关的核心功能开发&#xff0c;经常会有读者私信我&#xff0c;对于开发新人而言&#xff0c;如何快速学习 API 设计&#xff0c;我简单总结了一下&#xff1a; 1. 学习基础知识&#xff1a;学习HTTP、RESTful AP…

Vue表单基本操作-收集表单数据

收集表单数据 使用vue中的v-model收集表单里面的数据&#xff0c;不同的表单元素配合v-model会有不同的写法和技巧 本次的表单元素包括&#xff1a;文本框&#xff0c;单选&#xff0c;多选&#xff0c;下拉框&#xff0c;文本域 编写表单元素 首先编写表单元素&#xff0c;…

IT项目管理 PPT 选择题【太原理工大学】

单选题&#xff0c;10*2分20分 填空题&#xff0c;10*2分20分 判断题&#xff0c;10*1分10分 画图题&#xff0c;10分 进度计算题&#xff0c;15分 成本计算题&#xff0c;15分 简答题&#xff0c;5*2分10分 重点章节&#xff1a;3、4、5、6、7章 我觉得小题应该是在 PP…

如何在短时间内完成短视频app的上线及推广?

作为一款充满活力和创意的短视频app&#xff0c;想要快速上线并赢得用户的喜爱是一项艰巨的任务。在本文中&#xff0c;我们将探讨如何在短时间内完成短视频app的上线及推广。 短视频app搭建 首先&#xff0c;要成功地上线一款短视频app&#xff0c;您需要一套高质量的小视频…

从零入门激光SLAM(八)——ROS常用消息

大家好呀&#xff0c;我是一个SLAM方向的在读博士&#xff0c;深知SLAM学习过程一路走来的坎坷&#xff0c;也十分感谢各位大佬的优质文章和源码。随着知识的越来越多&#xff0c;越来越细&#xff0c;我准备整理一个自己的激光SLAM学习笔记专栏&#xff0c;从0带大家快速上手激…

Scrapy框架 -- POST请求实现案例

一、创建一个Scrapy项目fanyi&#xff0c;并进入该项目创建&#xff0c;fanyipc爬虫文件 scrapy startproject fanyi cd fanyi scrapy genspider example example.com 二、修改配置文件settings&#xff0c;关闭君子协议&#xff0c;只看报错信息&#xff0c;自定义UA头 ROB…