这篇文章并非单一的介绍JDK17的新特性,而是将jdk8到jdk17之间所有新加入的特性进行了简单的汇总,罗列一系列重要的改动,以便从JDK8升级到JDK17.

模块化开发

这并非jdk17的新特性,模块化在jdk9中加入,模块化的好处就是开发者可以根据需要引用某个依赖的指定部分,而不是引入这个依赖的全部。以此达到减少体积以及提高编效率的目的。
看一个例子:

  1. 新建一个项目,并创建一个model1,在model1中编写以下两个java类,并创建module-info,对外纰漏com.gsk.module1.test1这个包
  2. 创建一个model2,在model2中引入model1,并尝试调用model1中的类

    如果熟悉前端开发的话,对此不难发现这些熟悉的modulerequiresexports等关键字。也更容易去掌握这其中的应用场景。但对于重度依赖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可以将具体引发空指针的变量名称和位置披露出来,对于新手来说,可以更方便问题排查。

允许方位外部存储器

没有想到会有什么作用,感觉这很不安全,在我的印象中,只有开发游戏外挂或者开发一些破解器才会用到这些。不重点介绍,有兴趣的可以直接查阅相关文档。

密封类

通过sealedpermits关键字可以创建一个密封类,这个密封类只允许特定的类对其进行扩展和实现

// 创建一个密封的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,需要注意的一些新特性相关推荐

  1. jdk11新特性,是否有必要从JDK8切换到JDK11

    文章目录 1.完全支持Linux容器(包括docker) 2.ZGC 3.全新的 HTTP 客户端 API 4.模块化(Module) 5.其他 6.是否切换到JDK11 随着2022年jdk11的使 ...

  2. JDK8 到 JDK17 各个版本的重要特性一览

    点击"终码一生",关注,置顶公众号 每日技术干货,第一时间送达! JDK8新特性(2014年初)(LTS版本) 1.Lambda表达式 2.函数式编程 3.接口可以添加默认方法和静 ...

  3. JDK 每半年就会更新一次新特性,再不掌握就要落伍了:JDK8 的新特性

    该图片由Alexandr Podvalny在Pixabay上发布 你好,我是看山. 本文收录在 <Java 进阶> 系列专栏中. 从 2017 年开始,JDK 版本更新策略从原来的每两年一 ...

  4. jdk8新特性 lambda表达式详解

    本文主要讲到的内容有: 一- 前言 二- 背景 三- lambda表达式的语法 四- Lambda程序例子 4-1 Runnable Lambda 4-2 Comparator Lambda 4-3 ...

  5. JDk8的新特性-流和内部iteration

    JDK8到今天已经出了好几年了  但是在公司能用到新特性的地方还是很少, 去年的时候当时项目老大要求我们用最新的写法来写Java 刚开始看到用stream写出来的代码一脸懵逼,内心就在想  这是Jav ...

  6. Lambda使用——JDK8新特性

    文章目录 Lambda 简介 Lambda 表达式 Lambda 常用测试 Optional 常用方法测试 Lambda 简介 Lambda表达式是JDK8的新特性,可以取代大部分的匿名内部类,写出更 ...

  7. 并发调试和JDK8新特性

    第一个是多线程的调试方法,第二个是关于dump的分析,我们在系统出问题的时候,可以看有哪些线程在运行,每个线程的堆栈是什么情况,如果我们发现有些线程被卡死了,我们从堆栈的分析当中呢,往往可以得到一些有 ...

  8. JDK8新特性之函数式接口

    转载自 JDK8新特性之函数式接口 什么是函数式接口 先来看看传统的创建线程是怎么写的 Thread t1 = new Thread(new Runnable() {@Overridepublic v ...

  9. JDK8之新特性扩展篇

    转载自 JDK8之新特性扩展篇 BASE64 base64编码解码已经被加入到了jdk8中了. import java.nio.charset.StandardCharsets; import jav ...

最新文章

  1. ubuntu16.04 sudo apt-get update解决Hash sum错误
  2. 递归查询树状结构某个确定的节点
  3. SQLite添加列的限制
  4. python中strip()的陷阱
  5. 精选30道Java笔试题解答
  6. 《必然》九、享受重混盛宴,是每个人的机会
  7. 算法题3 二分查找法
  8. Java多线程(学习总结,持续更新)
  9. 链接属性rel=’external’、rel=’nofollow’、rel=’external nofollow’三种写法的区别...
  10. VS2012下基于Glut OpenGL GL_QUAD_STRIP示例程序:
  11. WebService远程调试
  12. iis服务器怎么限制运行asp文件,Win2008 r2 IIS7.5制定目录禁止执行脚本的方法
  13. 《嵌入式系统Linux内核开发实战指南(ARM平台)》书评
  14. VMware Server 2.0下载和序列号正版
  15. Android 文字转语音之TextToSpeech
  16. 求解哈夫曼编码Java实现,哈夫曼编码(Java)
  17. “舌战群儒”的技术分析
  18. 3D变化——旋转的立方体
  19. 【阿里云仓库 可用 2022】IDEA MAVEN setings.xml 配置
  20. storyboard 使用

热门文章

  1. 粘贴板管理 android,安卓剪贴板管理(Clipper Plus)
  2. 2022年11月华南师范大学自考本科-计算机信息管理课程实验—《数据库系统原理》实践题目
  3. putty使用方法,中文教程
  4. koa--更富有表现力、更健壮的 Web 框架
  5. UItableView+Mansory自定义Cell小Demo
  6. 关于在eclipse中中文汉字乱码的解决方式
  7. [数据][json格式] 2016年统计用区划代码和城乡划分代码
  8. 智能突触《Continual Learning Through Synaptic Intelligence》(SI)
  9. 安卓平台 使用Jword生成word文档到本地【亲测成功】
  10. linux(shell)查看文件时间戳