从JDK8到JDK17,需要注意的一些新特性
这篇文章并非单一的介绍JDK17的新特性,而是将jdk8到jdk17之间所有新加入的特性进行了简单的汇总,罗列一系列重要的改动,以便从JDK8升级到JDK17.
模块化开发
这并非jdk17的新特性,模块化在jdk9中加入,模块化的好处就是开发者可以根据需要引用某个依赖的指定部分,而不是引入这个依赖的全部。以此达到减少体积以及提高编效率的目的。
看一个例子:
- 新建一个项目,并创建一个
model1
,在model1
中编写以下两个java类,并创建module-info
,对外纰漏com.gsk.module1.test1
这个包
- 创建一个
model2
,在model2
中引入model1
,并尝试调用model1
中的类
如果熟悉前端开发的话,对此不难发现这些熟悉的module
、requires
、exports
等关键字。也更容易去掌握这其中的应用场景。但对于重度依赖maven的开发者来说,模块的概念用的可能不是很多。
JShell
引擎
在JDK8中,对于一些复杂的动态、可编程的配置,可以使用Nashorn
引擎去执行js代码,以达到动态变编程杂配置的目的,比如下面就是我开发的一套内部的工业系统的一部分,可以通过编写javascript
脚本去快速的动态编程一些东西。
但这个脚本引擎很久之前就被java移除了,JDK17中尽管可以使用第三方依赖库提供的引擎,但由于javascript更新越来越频繁、并且javascript
中的对象模型与java存在差异,并不能完美的与java融合。因此你需要一个更强大的引擎, 那就是JShell
。
JShell
也不是jdk17的特性,它同样在jdk9中被加入。JShell的出现,使得java的字节码代码可以像脚本语言一样去动态编程。
如果你的设备中安装了JDK9即以上的版本,可以在终端中输入jshell
,进入JShell
,并编写脚本进行测试,同时按tab键可以调出候补提示。
构建多版本兼容的jar
javac -d build --release 8 src/java/com/company/*.java
javac -d build17 --release 17 src/java17/com/company/*.java
jar --create --main-class=Test --file test.jar -C build . --release 17 -C build17 .
此时,让这个jar包在JDK8中运行时,执行的时src/java
下编译的字节码,当这个jar包在JDK17上运行时则执行的是src/java17
下编译的字节码。
需要注意的是,这个特性依然是在JDK9中就被引入了
接口的私有方法
在JDK17中,允许interface中携带private方法,这个private方法允许被自身default修饰的方法调用。
public interface Test{default test1(){Test2();}private void test2(){System.out.printin(“hello”)}
}
String
底层变更
在以前的String底层是一个char[], 而现在String底层变更为byte[],以此使得内存的利用率更加高效。
增强的StreamAPI
takeWhile
方法
takeWhile()
的用法和filter()的用法一致,但结果有所不同,filter是遍历流中所有元素,并舍弃所有不符合条件的元素。而takewhile()则是从开始进行遍历,如果出现不符合条件的元素时,就舍弃并中断流。也就是说,当流中出现不符合条件的元素时,即使后面的元素符合条件也依然会被舍弃。有点像&
与 &&
的意思,举个例子:
Stream.of(1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1).filter(i -> i < 4 )
.forEach(System.out::print);
// 打印结果为:123321
Stream.of(1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1).takeWhile(i -> i < 4 )
.forEach(System.out::print);
// 打印结果为:123
dropWhile
方法
dropWhile()
正好与takeWhile()
相反,前者将得到从头开始的元素,而后者返回剩余的元素,但需要注意的一点是,千万不要认为他是反向遍历,因为它得到的结果是正序的。而反向遍历的结果是反序的。这个细节不注意的话,可能会影响实际生产冲的业务。
ofNullable
方法
这个方法允许初始化一个空的流
Stream.ofNullable(null).count()
// 结果为0
增强的iterate
方法
Iterate方法现在可以传入三个表达式,依此来实现复杂的迭代。
Stream.iterate(1,(x) -> x <= 10, (x) -> x + 1).forEach(System.out::print);
Records
(类)
Records
是一种特殊的类,用于快速构建java实体
public record Person(String name ,Integer age) {}
类似于以下代码:
@Data
public class Person{private String name;private Integer age;
}
var
关键字
现在Java的局部变量可以使用var关键字,可以进行变量类型推断,就像javascript一样。
var a = “ABC”;
System.out.println(a.getClass())
新的HttpClient
参考以下类,使用很简单,可以阅读java.net.http中的相关API
java.net.http.HttpClient
java.net.http.HttpRequest
java.net.http.HttpResponse
快速构建集合
参考以下代码,同时List集合可以通过重载的toArray方法方便的转换为数组
List.of(“a”, “b”, “c”);
Map.of(“ak”, “av”, “bk”, “bv”);
通过Files
类快速读写
Files.writeString(Path.of("./", "tmp.txt"), // 路径"hello, jdk11 files api", // 内容StandardCharsets.UTF_8); // 编码
String s = Files.readString(Paths.get("./tmp.txt"), // 路径
StandardCharsets.UTF_8); // 编码
增强的String
类
strip
等系列方法
相对于trim
, strip
可以去掉unicode空格, 同时还有stripLeading()
和stripTrailing()
方法用于分别取出首空和尾空。因此不再建议使用trim
,而是strip
isBlack
方法和isEmpty
前者忽略空格,后者只要有长度就判为非空。通常对于形参校验的情况下,应使用isBlack
lines
方法
lines()
方法会将一个多行字符串拆分为多个单行字符串,可以方便的以“行“来遍历多行字符串。
repeat
方法
该方法可以构建一个由多个相同字符串组合的字符串。很绕口,代码解释如下:
String str = “hello!”.repeat(2);
// 其中,str被赋值为 “hello!hello!”
文本块支持
通过三个"
可以直接编写一个文本块,而不需要繁琐的代码构建。这对于写SQL或一切其他动态脚本时非常实用。随着IDE不断进步,未来会更美好。
String str =
"""
public static void main(String[] args){System.out.println("hello world!")
}
"""
等同于:
String str =
"public static void main(String[] args){\n" +
" System.out.println(\"hello world!\")\n" +
"}"
增强的switch
表达式
T result = switch (arg) {case L1 -> e1;case L2 -> e2;default -> e3;
};
NumberFormat
增加了压缩数字的支持
String number = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT).format(1000);
// 其中number = “1k“
增强的instanceof
if (obj instanceof String str) {System.out.println("str length:" + str.length());
} else {System.out.println("obj not string.");
}
码农福音,增强的NullPointerExceptions
增强后的NullPointerExceptions
可以将具体引发空指针的变量名称和位置披露出来,对于新手来说,可以更方便问题排查。
允许方位外部存储器
没有想到会有什么作用,感觉这很不安全,在我的印象中,只有开发游戏外挂或者开发一些破解器才会用到这些。不重点介绍,有兴趣的可以直接查阅相关文档。
密封类
通过sealed
和permits
关键字可以创建一个密封类,这个密封类只允许特定的类对其进行扩展和实现
// 创建一个密封的Hello接口,只允许Hello2类对其进行实现
public interface sealed class Hello permits Hello2{}
同时,也可以通过在子类或实现类添加non-sealed关键字来进行解封。
支持Unix套接字
通过java.net.UnixDomainSocketAddress
可以连接unix套接字,以此来实现更安全的内部通信。
直接打包成可执行程序
支持将Java程序打包为对应平台的可执行程序
linux: deb和rpm
mac: pkg和dmg
Windows: msi和exe
假如我们在lib目录下有一个jar包组成的应用,并且main.jar包含main方法,则可以使用下面的语句产生对应平台的可执行程序
jpackage --name myapp --input lib --main-jar main.jar
如果main.jar的MANIFEST.MF没有指定main函数,则需要在命令行中指定
jpackage --name myapp --input lib --main-jar main.jar --main-class myapp.Main
Clinker
类
通过Clinker
可以更方便的执行某个原生C函数,具体参考相关文档。
macOS/AArch64 端口
将 JDK 移植到新架构 macOS/AArch64
期待未来需求
新的 macOS 渲染管线
需要使用新的 Apple Metal
框架为 macOS 提供新的 Java 2D
渲染管道。与今天一样,Java 2D
完全依赖于 OpenGL
。虽然 Apple 在 macOS 10.14 中弃用了 OpenGL
渲染库,但 Metal
框架取代了 OpenGL
渲染库。
反射相关
在java.lang.Class
中新增了两个方法
boolean isSealed()
Class<?>[] getPermittedSubclasses()
前者用于判断该类是否为密封类,后者则用来获得当前密封类所允许扩展的Class
列表。
从JDK8到JDK17,需要注意的一些新特性相关推荐
- jdk11新特性,是否有必要从JDK8切换到JDK11
文章目录 1.完全支持Linux容器(包括docker) 2.ZGC 3.全新的 HTTP 客户端 API 4.模块化(Module) 5.其他 6.是否切换到JDK11 随着2022年jdk11的使 ...
- JDK8 到 JDK17 各个版本的重要特性一览
点击"终码一生",关注,置顶公众号 每日技术干货,第一时间送达! JDK8新特性(2014年初)(LTS版本) 1.Lambda表达式 2.函数式编程 3.接口可以添加默认方法和静 ...
- JDK 每半年就会更新一次新特性,再不掌握就要落伍了:JDK8 的新特性
该图片由Alexandr Podvalny在Pixabay上发布 你好,我是看山. 本文收录在 <Java 进阶> 系列专栏中. 从 2017 年开始,JDK 版本更新策略从原来的每两年一 ...
- jdk8新特性 lambda表达式详解
本文主要讲到的内容有: 一- 前言 二- 背景 三- lambda表达式的语法 四- Lambda程序例子 4-1 Runnable Lambda 4-2 Comparator Lambda 4-3 ...
- JDk8的新特性-流和内部iteration
JDK8到今天已经出了好几年了 但是在公司能用到新特性的地方还是很少, 去年的时候当时项目老大要求我们用最新的写法来写Java 刚开始看到用stream写出来的代码一脸懵逼,内心就在想 这是Jav ...
- Lambda使用——JDK8新特性
文章目录 Lambda 简介 Lambda 表达式 Lambda 常用测试 Optional 常用方法测试 Lambda 简介 Lambda表达式是JDK8的新特性,可以取代大部分的匿名内部类,写出更 ...
- 并发调试和JDK8新特性
第一个是多线程的调试方法,第二个是关于dump的分析,我们在系统出问题的时候,可以看有哪些线程在运行,每个线程的堆栈是什么情况,如果我们发现有些线程被卡死了,我们从堆栈的分析当中呢,往往可以得到一些有 ...
- JDK8新特性之函数式接口
转载自 JDK8新特性之函数式接口 什么是函数式接口 先来看看传统的创建线程是怎么写的 Thread t1 = new Thread(new Runnable() {@Overridepublic v ...
- JDK8之新特性扩展篇
转载自 JDK8之新特性扩展篇 BASE64 base64编码解码已经被加入到了jdk8中了. import java.nio.charset.StandardCharsets; import jav ...
最新文章
- ubuntu16.04 sudo apt-get update解决Hash sum错误
- 递归查询树状结构某个确定的节点
- SQLite添加列的限制
- python中strip()的陷阱
- 精选30道Java笔试题解答
- 《必然》九、享受重混盛宴,是每个人的机会
- 算法题3 二分查找法
- Java多线程(学习总结,持续更新)
- 链接属性rel=’external’、rel=’nofollow’、rel=’external nofollow’三种写法的区别...
- VS2012下基于Glut OpenGL GL_QUAD_STRIP示例程序:
- WebService远程调试
- iis服务器怎么限制运行asp文件,Win2008 r2 IIS7.5制定目录禁止执行脚本的方法
- 《嵌入式系统Linux内核开发实战指南(ARM平台)》书评
- VMware Server 2.0下载和序列号正版
- Android 文字转语音之TextToSpeech
- 求解哈夫曼编码Java实现,哈夫曼编码(Java)
- “舌战群儒”的技术分析
- 3D变化——旋转的立方体
- 【阿里云仓库 可用 2022】IDEA MAVEN setings.xml 配置
- storyboard 使用
热门文章
- 粘贴板管理 android,安卓剪贴板管理(Clipper Plus)
- 2022年11月华南师范大学自考本科-计算机信息管理课程实验—《数据库系统原理》实践题目
- putty使用方法,中文教程
- koa--更富有表现力、更健壮的 Web 框架
- UItableView+Mansory自定义Cell小Demo
- 关于在eclipse中中文汉字乱码的解决方式
- [数据][json格式] 2016年统计用区划代码和城乡划分代码
- 智能突触《Continual Learning Through Synaptic Intelligence》(SI)
- 安卓平台 使用Jword生成word文档到本地【亲测成功】
- linux(shell)查看文件时间戳