一文详解JDK8常用10个更新特性

今日一语:当你发现编程的规律就是世界的规律时,你就是一名真正的程序员

1 Lambda(蓝布达)表达式

编译后会产生一个$XXXImpl1的编译文件,与匿名内部类相似,但不等同于匿名内部类。
其原理是将方法作为参数进行传递,
JVM会使用一个动态调用的指令调用函数式接口中的方法。
同时使用lambda将会使代码更简洁易读。
别名:【闭包】
使用方式:①使用JDK自有的函数式接口【接口列表】②自定义函数式接口使用。
如下:
1)自定义函数式接口,并且只定义一个方法,返回值与参数没有限制

/** 接口1 要点:参数再封装返回 */ 
@FunctionalInterface 
public interface EventExector { String event(String methodName); 
} 
/** 接口2 要点:计算两个数字之和返回 */@FunctionalInterface public interface LambdaInterface1 { int mathOption(int a,int b); 
}/** 接口3 要点:获取当前时间的时间戳 */ @FunctionalInterface public interface LambdaInterface2 { void catCurrentDate(Date date); } /** 接口4 要点:将Map中的value取出放入一个list中 */ @FunctionalInterface public interface LambdaInterface3 { void copyMap(Map<String,Integer> map, List<Integer> list); } /** 接口5 要点:无返回无参数 */ 

2)将定义号的函数式接口通过参数传入

/** 接口1注入方法1 */ 
private static int operation(int a,int b,LambdaInterface1 interface1) { return interface1.mathOption(a,b); 
} 
/** 接口2注入方法2 */ 
private static String realize(String target,EventExector exector) { return exector.event(target); 
} 
/** 接口3注入方法3 */ 
private static void getDate(Date date,LambdaInterface2 interface2) { interface2.catCurrentDate(date); 
} 
/** 接口4注入方法4 */ 
private static void replaceMap(LambdaInterface3 interface3, Map map,List list) { interface3.copyMap(map,list); 
} 
/** 接口5注入方法5 */ 
private static void goToWay(LambdaInterface4 interface4) { interface4.onTheWay(); 
} 
  1. 调用方法,其中()中的参数为传入的参数, -> 代表lambda表达式的箭头指引符,
    箭头符号的后面,需注意,如果有返回值,有两种返回书写方式。
    在大括号中,使用return返回,没有大括号,直接将返回值写在箭头符后面。
    如果没有返回值,箭头符后面的指引内容将是纯粹的Java指令,不会有任何返回。
/** 传入一个参数 有返回 */ 
System.out.println(realize("xx", (x) -> "HELLO GUYS! " + x)); 
/** lambda 传入两个参数 有返回 */ 
System.out.println(operation(1, 2, (a, b) -> a + b)); 
/** 传入一个参数,无返回 */ 
getDate(new Date(), date -> { long time = date.getTime(); System.out.println("当前内容时间戳"+time); 
}); 
/** 传入两个参数,无返回 */ 
Map<String,Integer> map = new Hashtable<>(); 
map.put("one",1);
map.put("two",2); 
map.put("three",3); 
map.put("four",4); 
List list = new ArrayList(); 
replaceMap((map1, list1) -> { for (String s : map.keySet()) {list.add(map.get(s)); } },map,list); 
/** 无参数无返回 */ 
goToWay(() -> System.err.println("请纠正你的方向!")); 

4)使用lambda注意事项

  1. 外部局部变量[基本类型]放在lambda中使用时,必须使用final修饰.
    因为lambda中外部局部变量无法传递!变量值无法改变。
    final:
    ① 如果修饰给基本类型变量,则表示值不可改变;
    ② 如果修饰引用类型变量,那么变量的引用地址不可改变,但是属性值是可以改变的。

  2. 考虑性能,如果代码不繁多,可以不用lambda

@Test 
public void lambda2() { String name = "我醉了"; int age = 12; sayHello("高进",message -> { name = "dsa";  // 此处编译会报错 age = 11; // 此处编译会报错 System.out.println(message+name+age); }); 
} 

2 双冒号::语法

这种 [方法引用] 或者说 [双冒号运算] 对应的参数类型是 Function<T,R> T表示传入类型,R表示返回类型。
比如表达式 person -> person.getAge(); 传入参数是 person,返回值是 person.getAge()
那么方法引用 Person::getAge 就对应着 Function<Person,Integer> 类型。

/** 所需函数式接口 */ 
@FunctionalInterface 
public interface Merchant<T> { T get(); 
} 
/** 接口使用类 */ 
public class Computer { public static Computer create(final Merchant<Computer> merchant) { return merchant.get(); } public static void getComputer(final Computer computer) { System.out.println("地址:"+computer.toString()); } public void getPro(final Computer computer) { System.out.println(computer.hashCode()); } public void getDate() { System.out.println(LocalDate.now().get(ChronoField.YEAR)); } public void getTime() { System.out.println(LocalTime.now().get(IsoFields.DAY_OF_QUARTER)); } 
} 

主要有四种类型:
1)构造器引用 [Class::new]
Computer computer = Computer.create(Computer::new);
2)静态方法引用 [Class::static_method]

List<Computer> list = Arrays.asList(computer); 
list.forEach(Computer::getComputer); 

3)特定类的任意对象的方法引用 [Class::method]

List<Computer> list = Arrays.asList(computer);
list.forEach(Computer::getDate);
list.forEach(Computer::getTime); 

4)特定对象的方法引用 [instance::new]

List<Computer> list = Arrays.asList(computer); 
final Computer huawei = Computer.create(Computer::new);`
list.forEach(huawei::getPro); 

3 Optional

JDK8处理空指针异常的工具类,减少空指针判断,可以存储空对象
只有两个值,一个是原本值,一个是空值

/** 静态方法 */ 
Optional.empty() 返回一个空的Optional对象 
Optional.of() 返回一个指定非null值的Optional 
Optional.ofNullable() 如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional	
/** 实例方法 */ 
optional.hashcode 返回存在值的哈希码,如果值不存在 返回 0 
optional.toString 返回一个Optional的非空字符串,用来调试 
optional.get 如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException 
optional.equals 判断其他对象是否等于 Optional 
optional.isPresent 如果值存在则方法会返回true,否则返回 false 
optional.ifPresent 如果值存在则使用该值调用 consumer , 否则不做任何事情 
optional.filter 如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional
optional.flatMap 如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional 
optional.orElse 如果存在该值,返回值, 否则返回 other 
optional.map 如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional 
optional.orElseGet 如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果 
optional.orElseThrow 如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常 

4 Stream

/** 生成流 */ 
list.stream() list.parallelStream() 
/** 所有操作 */ 
forEach() -> 循环操作 filter() -> 条件满足 map() -> 值处理 sorted()-> 排序 limit() -> 控制数量 summaryStatistics() -> 数据统计
在之前需要使用mapTo系列方法,也就是前提需要有数据流(int,float,double),主要有最大值,最小值,总和,总数,平均数
collect(Collectors.toList()) -> 转换成集合 collect(Collectors.joining(分隔符)) -> 将字符串内容合并到一起 
/** 代码示例 */ 
/** Stream 得到集合中元素值大于等于7的元素数量 */ 
List<Integer> numbers = Arrays.asList(1, 2, 2752, 2200, 7857, 6, 7, 8, 45, 54, 78, 857, 3, 357857, 86, 200780); 
numbers.stream().filter(obj -> obj % 2 == 0).limit(5).map(obj -> obj << 2).sorted((o1, o2) -> o2 - o1).forEach(integer -> {System.out.print(integer+"\t"); }); 
/** 使用Join */ 
List<String> stringList = Arrays.asList("张三","李四","王五","赵六","钱七","胡八"," "); 
String collect = stringList.stream().collect(Collectors.joining("先生,")).trim(); 
// 取出字符串尾部的 ',' 
System.out.println(collect.substring(0,collect.length()-1)); 
========控制台出入如下========= 
11008	8800	32	24	8	 
张三先生,李四先生,王五先生,赵六先生,钱七先生,胡八先生 

5 时间API

/** 月份支持 获取单独月份的支持 */
Month 
/*月份天数支持 可以获取月日格式的时间 */
MonthDay 
/**年份支持 可以获取年份*/
Year 
/*年份月支持 获取年月格式的时间*/
YearMonth 
/*时间戳操作 sql包中的获取时间戳中的方法*/
TimeStamp
/*瞬时时间 获取时间戳格式的时间*/ 
Instant 
/*星期支持 星期天数的格式时间获取*/
DayOfWeek 
/*日期支持 只获取基本的日期格式的时间。如【年-月-日】*/
LocalDate 
/*日期时间支持 获取日期时间支持,不包含时区与星期。,如【年-月-日T时:分:秒.Nano秒】,其中T分隔符*/
LocalDateTime
/*时间支持 只支持时间,不封装时区及任何时间信息*/ 
LocalTime 
/*日期时间转换器 提供日期时间格式的转换*/
DateTimeFormatter 
/*单线程日期时间转换器 只有一个返回字符串的静态方法*/
DateTimeFormatterBuilder

6 重复注解与类型注解

/** 重复注解,可以重复使用,原理是用了注解容器 **/ 
@Retention(RetentionPolicy.RUNTIME) 
@Repeatable(Annos.class) 
public @interface Anno { String value(); 
} 
@Retention(RetentionPolicy.RUNTIME)  
@interface Annos { Anno[] value(); 
} 

使用重复注解的原理使用了注解容器,实际上被声明的类上的注解是容器注解

/** 类型注解主要就是泛型与声明类型的时候可以使用,保证了程序的健壮性 */ 
/** 定义一个可以使用在类型上的注解 */ 
@Retention(RetentionPolicy.RUNTIME) 
// TYPE_USE 用于类型 
TYPE_PARAMETER 用于表示泛型 
@Target(ElementType.TYPE_USE) 
public @interface MyTest { String value() default ""; 
} 

7 concurrent并发包

// JUC包是jdk1.8为并发编程提供的工具包 提供了一些并发工具实现,后续补充

8 默认方法

在JDK8之前,一旦修改了接口中的方法,所有实现类都必须改动。
为了不影响之前的版本,提供在接口中定义默认方法的实现。
在方法前修饰default,并在代码域中编写默认内容

public interface Vehicle { /** 默认方法 */ default void print() { System.out.println("我是一辆车!"); } 	/** 静态方法 */static void hornBlock() { System.out.print("我要超车了!");} 
} 

9 Base64编码

// 编码 
private static String printEncoding(String str) { Base64.Encoder encoder = Base64.getEncoder(); byte[] encode = encoder.encode(str.getBytes()); return new String(encode); 
} 
// 解码 
private static String printDecoding(String str) { Base64.Decoder decoder = Base64.getDecoder(); byte[] decode = decoder.decode(str.getBytes()); return new String(decode); 
} 

10 内置函数式接口的应用

/** 菜鸟教程实例 */ 
https://www.runoob.com/java/java8-functional-interfaces.html 
/** 方法调用 */ 
public static void main(String[] args) { 
/** BiConsumer<T,U> 接收两个参数,不返回任何结果 */ 
getSomeSubject((s, integer) -> System.out.println(integer),"张三",12); 
/** BiFunction<T,U,R> 接收两个参数,返回一个结果 */ 
String someSubject = getSomeSubject((num1, num2) -> {return num1*num2+"";
},12,10); 
System.out.println("返回的结果为:"+someSubject); } 
// 方法定义 
private static String getSomeSubject(BiFunction<Integer,Integer,String> function,Integer num1,Integer num2) { return function.apply(num1,num2); 
} 
private static void getSomeSubject(BiConsumer<String,Integer> consumer,String name,Integer age) {consumer.accept(name,age); 
} 

感谢你的关注!有更多建议或疑问欢迎下方讨论…

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

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

相关文章

【深入浅出设计模式--命令模式】

深入浅出设计模式--命令模式 一、背景二、问题三、解决方案四、试用场景总结五、后记 一、背景 命令模式是一种行为设计模式&#xff0c;它可以将用户的命令请求转化为一个包含有相关参数信息的对象&#xff0c;命令的发送者不需要知道接收者是如何处理这条命令&#xff0c;多个…

php文件上传功能(文件上传)

实现文件上传是Web开发中常用的功能之一&#xff0c;而PHP也是支持文件上传的。那么&#xff0c;下面我们就来介绍一下常用的PHP实现文件上传的方法。 使用HTML表单实现文件上传 HTML表单是Web开发中最基本的元素之一&#xff0c;它可以接收用户输入的数据&#xff0c;并通过…

Python 笔记03(多线程)

一 打开命令行&#xff0c;查看本机IP windows r 命令行输入&#xff1a;cmd ipconfig 然后查看IPv4的地址&#xff1a;192.168.1*6.1 ipconfig 二 函数式多进程 from multiprocessing import Process import os, timedef func(name):print(进程的ID&#xff1a;, os.g…

大数据时代,数据治理

一、大数据时代还需要数据治理吗&#xff1f; 数据平台发展过程中随处可见的数据问题 大数据不是凭空而来&#xff0c;1981年第一个数据仓库诞生&#xff0c;到现在已经有了近40年的历史&#xff0c;相对数据仓库来说我还是个年轻人。而国内企业数据平台的建设大概从90年代末…

Docker 自动化部署(保姆级教程)

Docker 自动化部署 1. jenkins 介绍1.1 参考链接&#xff1a;1.2 jenkins 概述1.3 jenkins部署项目的流程 2. jenkins 安装2.1 基于docker 镜像2.2 启动 jenkins 后端服务2.3 登录 jenkins 服务后端 3. jenkins自动化部署开始3.1 下载需要的插件3.2 创建任务3.2.1 描述3.2.2 配…

使用bash脚本编译Qt工程

最近在搭建Qt工程的编译服务器&#xff0c;需要通过shell脚本执行工程的编译过程&#xff0c;写在这里&#xff0c;总结最近的工作。 1. 构建过程 以Windows为例&#xff0c;在QtCreator中左侧选择“项目”便可以看到编译的指令和参数&#xff0c;这些操作也会在我们点击“构建…

git管理常用命令

1、下载代码 git clone 地址2、软件代码提交 1、查看工程中被修改的文件&#xff1a;git status 2.将不需要提交的文件回退&#xff1a;git check <文件路径> 3.更新工程到最新&#xff1a;git pull 4.将本地代码添加到暂存区&#xff1a;git add <将要提交的文件路…

CAN总线数据链路层

CAN报文帧种类: 数据帧:用于发送节点向接收节点传送数据,是使用最多的帧类型远程帧:用于接收节点向某个发送节点请求数据错误帧:用于当某节点检测出错误时向其他节点通知错误的帧过载帧:用于接收节点向发送节点通知自身接收能力的帧帧间隔:将数据帧或远程帧与前面的帧分…

MySQL学习笔记14

MySQL查询之多表查询&#xff1a;&#xff08;了解&#xff09;但是还是要掌握比较好。 1、什么是多表查询&#xff1f; 查询五子句是单表查询&#xff0c;实际工作中&#xff0c;也可能会接触到一个复杂的多表查询。 2、Union 联合查询&#xff1a; union联合查询的作用&…

ElementUI之首页导航与左侧菜单

目录 一、Mock 1.1 什么是Mock.js 1.2 安装与配置 1.2.1 安装mock.js 1.2.2 引入mock.js 1.3 mock.js使用 1.3.1 定义测试数据文件 1.3.2 mock拦截Ajax请求 1.3.3 界面代码优化 二、总线 2.1 定义 2.2 类型分类 2.3 前期准备 2.4 配置组件与路由关系 2.4.1 配置…

Java8实战-总结35

Java8实战-总结35 重构、测试和调试使用 Lambda 重构面向对象的设计模式工厂模式 测试 Lambda 表达式测试可见 Lambda 函数的行为测试使用 Lambda 的方法的行为将复杂的 Lambda 表达式分到不同的方法高阶函数的测试 重构、测试和调试 使用 Lambda 重构面向对象的设计模式 工厂…

JSON数据获取指南!

在互联网时代&#xff0c;数据是金钱的来源。然而&#xff0c;要从海量的网页中提取需要的数据并不容易。本文将带你了解如何使用Node.js编写简易爬虫程序&#xff0c;帮助你轻松获取并处理JSON数据&#xff0c;让你不再为数据发愁。 一、准备工作 安装Node.js&#xff1a;确保…

如何在控制台打印sql语句

步骤一&#xff1a; log4j2.xml中做以下配置 <logger name"xxx.infrastructure.mysql.mapper"level"debug" additivity"false"><appender-ref ref"Console"/></logger>步骤二&#xff1a;IDEA下载Free Mybatis Plu…

9、JavaSE总结

9、JavaSE总结 9.1 Java语言 9.1.1 MarkDown语法 9.1.2 简单的Dos命令 9.1.3计算机语言发展 9.1.4 Java的诞生 1995年诞生&#xff1a;JavaSE、JavaME、JavaEE 2006年Hadoop大数据系列 9.1.5 JDK、JRE JDK&#xff1a;开发者工具包、配置环境变量&#xff08;配置Java…

Vue Mock.js介绍和使用与首页导航栏左侧菜单搭建

前言&#xff1a; 因为使用Vue开发&#xff0c;组件写的太多&#xff0c;组件与组件之间的传递数据复杂&#xff0c;所以要用到Mock和Bus事件 一&#xff0c;关于Mock 1.1.什么是Mock.js Mock.js是一个模拟数据的生成器&#xff0c;用来帮助前端调试开发、进行前后端的原型分离…

upload-labs靶场未知后缀名解析漏洞

upload-labs靶场未知后缀名解析漏洞 版本影响&#xff1a; phpstudy 版本&#xff1a;5.2.17 ​ 1 环境搭建 1.1 在线靶场下载&#xff0c;解压到phpstudy的www目录下&#xff0c;即可使用 https://github.com/c0ny1/upload-labs1.2 已启动&#xff1a;访问端口9000&…

似然和概率

前言 高斯在处理正态分布的首次提出似然&#xff0c;后来英国物理学家&#xff0c;费歇尔 概率是抛硬币之前&#xff0c;根据环境推断概率 似然则相反&#xff0c;根据结果推论环境 P是关于x的函数&#xff0c;比如x为正面朝上的结果&#xff0c;或者反面朝上的结果&#xf…

数据大爆炸:大数据分析如何改变我们的世界

文章目录 大数据分析的基本概念数据的三个V大数据分析的技术 大数据分析在商业中的应用1. 个性化营销2. 风险管理3. 供应链优化4. 客户服务 大数据分析在医疗保健中的应用1. 疾病预测2. 患者治疗3. 医疗设备监控 大数据分析在科学研究中的应用1. 天文学2. 生物学3. 气象学 大数…

如何搭建自己的gitlab服务器

这里使用Termus工具连接服务器&#xff0c;然后根据步骤走即可&#xff01; 安装 1.配置yum源安装gitlab vim /etc/yum.repos.d/gitlab-ce.repo修改或新增下面配置并保存 [gitlab-ce] nameGitlab CE Repository baseurlhttps://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum…

pycharm中配置torch

在控制台cmd中安装好torch后&#xff0c;在pycharm中使用torch&#xff0c;需要进行简单设置即可。 在pycharm中新建一个工程&#xff0c;在file文件中打开setting 在setting中找到project interpreter编译器 找到conda environment的环境配置&#xff0c;设置好相应的目录 新…