从BenchMark可以看到,仅需要从JDK8升级到JDK17就能够获得64%的改进 — JavaOne开幕式
本文章的灵感来源于Java One开幕式上JDK开发者的这句话。JDK向前兼容的重要特性意味着,我们不需要改动任何代码只需要将运行源代码的JDK从8替换为JDK17就能够获得大量的提升(极地的成本)。
这篇文章讲汇总JDK8到JDK17的关键特性,理解为什么从JDK8到JDK17有着重要意义。
JDK底层/API语法:
JDK9
- 接口方法可以使用private修饰
- 支持http2.0和websocketAPI
- 模块化编程(对于依赖于Maven的开发者来说使用率和其产生的作用不高)
- String类底层数组从char[]变更为了byte[]。(byte能够在同样支持拉丁字符的情况下只占用1个字节,而char需要2个)
- 支持NumberFormat API,能够对数字进行格式化或者压缩
JDK10
- 推出var关键字支持局部变量类型推断,类似JS推断出值的真实类型
JDK11
- 集合API的增强
- 对Stream、Optional、集合API增强
JDK13
- Socket底层优化,引入NIO
- switch表达式添加yield关键字,用于返回结果,作用类似return
- 引入"""三双引号语法(文本块),内部不需要使用换行的转义字符。
JDK14
- instanceof关键字优化,代码块中会直接给对象赋值
- 引入record类,会自动生成构造器、getter、setter等方法,类似Lombok。
- NPE优化,可以打印具体哪个方法跑出了NPE,方便单行代码多个函数调用时的异常排查。(开发者福音)
JDK15
- 隐藏类Hiden Class
- 密封类 Sealed Class,密封类能够限定继承或者实现的子类。
- 对应java.lang.Class问类中新增了
isSealed
和getPermittedSubClasses()
两个方法用于判断密封类和密封类所允许的拓展Class列表
JDK16 正式的将record、instanceof特性引入到JDK版本中
JDK17 正式引入密封类sealed class
- 统一日志一步刷新
JVM优化:
JDK9
- 设置为G1默认垃圾回收器
JDK10
- 并行FullGC,优化G1的延迟(JDK9的Full GC只有单线程,而10之后会采用Young和Mixed相同数量的线程进行FullGC)
- 线程局部管控,支持在不执行全局VM安全点的情况下对线程执行回调方法,停止单个线程,而不需要停止所有线程。
JDK11
- 推出ZGC(随后经过了多次的优化,是JDK17中综合性能最好的垃圾收集器,根据JavaOne的介绍其目标是能够支持亚秒级别回收TB界别的堆,还没达到但已经非常强了)
JDK12
- 推出Shenandoan垃圾收集器(12, 仅支持Linux,)
- 拓展swtich表达式,支持返回值(12
- 优化G1收集器,将G1的垃圾分为强制回收和可选部分,提高GC效率
JDK13
- ZGC优化,将标记长时间的空闲对内存空间返回给OS,保证堆大小不会小于配置的最小堆内存
JDK15
- ZGC性能优化
新语法/API实际使用
val局部变量类型推断
标识符var不是关键字,而只是一个保留的类型名称,仅适用于局部变量,能够通过值来推断出值的数据类型过是什么。 示例
var str = "ABC"; //根据推断为 字符串类型
var l = 10L;//根据10L 推断long 类型
var flag = true;//根据 true推断 boolean 类型
var flag1 = 1;//这里会推断boolean类型。0表示false 非0表示true
var list = new ArrayList<String>(); // 推断 ArrayList<String>
var stream = list.stream(); // 推断 Stream<String>
反编译class文件:
String str = "ABC";
long l = 10L;
boolean flag = true;
int flag1 = true;
ArrayList<String> list = new ArrayList();
Stream<String> stream = list.stream();
switch表达式
- 现在支持使用switch赋值
- 引入了lambda表达式,
- 引入了yield语法,能够返回值,而不是使用break;
String result = switch (day) {
case "M", "W", "F" -> "MWF";
case "T", "TH", "S" -> "TTS";
default -> {
if(day.isEmpty())
yield "Please insert a valid day.";
else
yield "Looks like a Sunday.";
}
instanceof模式匹配
JDK14之前
if (obj instanceof Article) {
Article a= (Article) obj;
System.out.println(a.getAuthor());
}
JDK14之后
if (obj instanceof Article a) {
System.out.println(a.getAuthor());
}
NPE错误信息更详细
JDK14之前
Exception in thread "main" java.lang.NullPointerException at NullPointerExample.main(NullPointerExample.java:5)
JDK14之后
Exception in thread "main"
java.lang.NullPointerException: Cannot invoke "Blog.getAuthor()" because the return value of "Article.getBlog()" is null at NullPointerExample.main(NullPointerExample.java:4)
record记录类
record Author(){}
//or
record Author (String name, String topic) {}
编译器会自动生成构造函数、g/setter、equals/hashCode、toString等方法
sealed 密封类
// 创建一个密封的Hello接口,只允许Hello2类对其进行实现
public interface sealed class Hello permits Hello2{}
NumberFormat增加了对压缩数字的支持
String number = NumberFormat.getCompactNumberInstance(Locale.US,
NumberFormat.Style.SHORT).format(1000);
// 其中number = “1k“
String类API的增强
添加了strip()
,isBlack()
、isEmpty()
、lines()
、repeat()
等多个方法
strip()
看作是trim的增强,能够去掉unicode空格,对应的还有stripLeading()和stripTailing()isBlack()
和isEmpty()
两者是String类中内置的方法,但依然建议使用各个工具包下的StringUtils。因为使用内置方法时,如果对象为空会产生NPE;而工具类下的StringUtils则不会。lines()
会将单个多行字符才成多个单行字符repeat()
能够构建一个或多个相同字符串组合的字符串