目录
JDK5
基本数据类型自动装箱拆箱
可变参数
增强for
注解
泛型
枚举
概述
定义
常用方法
自定义构造方法
枚举类中的抽象方法
JDK7
二进制字面量
switch
异常
try-with-resources,自动关流
JDK11
FileInputStream增强
String类增强
Stream流增强
List增强
全新的垃圾回收器ZGC
ZGC的优势
可变类型var
概述
注意点
JDK17
增强型伪随机数发生器
RandomGeneratorFactory
RandomGenerator
强封装JDK的内部API
switch增强
密封类
全面提速
jdk5是java的标志性版本,提供了众多影响深远的功能,是java质变的版本
基本数据类型和其包装类的转换,运算,不再需要显式的使用构造方法,intValue()等方式,直接就可以互相运算,赋值
Integer a = 1;
int b = a;
int c = a + b;
方法的参数可以不是固定个数,编译器会隐式的使用一个数组去接收参数
注意
可变参数显然只能放在所有参数的最后,因为它会把所有的参数都接收
public static Integer getSum(int ... nums){
int sum = 0 ;
for(int num : nums){
sum += num;
}
return sum;
}
对于数组,集合,不再需要通过角标,迭代器去遍历,极大的简化了操作
for (Integer num : numArr/numList) {
System.out.println(num);
}
遍地开花的注解功能也是在jdk5引入
菱形泛型也是在jdk5引入
将一类变量的值罗列出来,变量的值只限于列举出来的值的范围内
举例:一周7天,一年12个月
public enum GenderEnum {
GENDER_0,GENDER_1;
}
E.values(); 获取枚举值数组,values()是编译器提供的方法,并不是枚举类本身携带的方法,这并不妨碍我们使用
E.valueOf("MONDAY"); 获取指定枚举值
简单的枚举类显然没办法满足我们的业务需求,因为我们不大可能把这些字段都定义为枚举类型,因此需要通过自定义构造丰富枚举的使用
public enum GenderEnum {
GENDER_0("0", "女"),
GENDER_1("1", "男");
private String key;
private String val;
//自定义构造
private GenderEnum(String key, String val) {
this.key = key;
this.val = val;
}
//通过key获取val
public static String toVal(String k) {
GenderEnum [] ems = values();
for (GenderEnum e : ems) {
if(e.k().equals(k)) {
return e.v();
}
}
return null;
}
//通过val获取key
public static String toKey(String v) {
GenderEnum [] ems = values();
for (GenderEnum e : ems) {
if(e.v().equals(v)) {
return e.k();
}
}
return null;
}
public static Integer toIntKey(String v) {
GenderEnum [] ems = values();
for (GenderEnum e : ems) {
if(e.v().equals(v)) {
return Integer.parseInt(e.k());
}
}
return null;
}
public static Map toMap() {
return Arrays.stream(values()).collect(Collectors.toMap(GenderEnum::k, GenderEnum::v));
}
//获取key
public String k() {
return key;
}
//获取val
public String v() {
return val;
}
}
枚举类中可以定义抽象方法,那么每个枚举值都要重写该方法,通常不会特别的使用
枚举还提供了专用的EnumMap,EnumSet,但通常也不会特别使用它们
public enum GenderEnum {
GENDER_1("1", "男") {
@Override
public String getString() {
return "男-字符串";
}
};
//抽象方法
public abstract String getString();
private String key;
private String val;
private RoleEnum(String key, String val) {
this.key = key;
this.val = val;
}
jdk8之前最重要的过渡版本
在二进制数前面加上0b,0B标记这是一个二进制数
System.out.println(0b110);
case语句可以用String类型进行匹配,是的没错,jdk7以前case表达式不可以用String类型
String month = "1";
switch (month) {
case "1":
return "一月";
case "2":
return "二月";
default:
return null;
}
多个catch可以合并到一个处理体,异常用 | 符号间隔
try {
...
} catch (NoSuchFieldException | IllegalAccessException e) {
...
} finally {
...
}
使用该方式,不再需要手动close()关流
//不需要手动关流,代码块执行完会自动关流,可以声明多个流
try(InputStream inputStream = file.getInputStream();
InputStream inputStream2 = file2.getInputStream()) {
...
inputStream1...
inputStream2...
}
//如果手动关流
try {
InputStream inputStream = file.getInputStream()
...
} catch(Exception e) {
...
} finally {
...
if(inputStream != null) {
inputStream .close();
}
}
jdk8之后第二个LTS版本,提供了新的垃圾回收期ZGC
FileInputStream可以直接写入FileOutputStream
fis.transferTo(fos);
str.isBlank(); //trim后是否为空
str.lines(); //按照终止符分割为stream流
str.repeat(num); //复制num次,组成新的字符串
str.strip();
str.stripLeading();
str.stripTrailing();
截止结算
takeWhile(),从集合中取出满足条件的元素,直到不满足条件
dropWhile(),从集合中移除满足条件的元素,直到不满足条件
从单个数据构造流
Stream.ofNullable(null);
Optional.of("foo").stream(); Optionals可以直接转为Stream
集合转数组
List sampleList = Arrays.asList("张三", "java 11");
// array = {"张三", "java 11"};
String[] array = sampleList.toArray(String[]::new);
GC暂停时间不会超过10毫秒
既能处理几百兆的小堆,也能处理几个T的大堆
和G1相比,应用吞吐能力不会下降超过15%
为未来的GC功能和利用colord指针以及Load barriers优化奠定了基础
ZGC是一个并发、基于region、压缩型的垃圾收集器,只有root扫描阶段会STW(strop the world,停止所有线程),因此ZGC的停顿时间不会随着堆的增长和存活对象的增长而变长
用法:-XX:UnlockExperimentalVMOptions -XX:+UseZGC2
允许使用var作为变量定义时的类型声明
var x = 10;
要在定义时进行初始化
var x;
x = "var"; //编译时提示无法推断类型
类型无法互相兼容
var x = 10;
x = "var"; //提示类型不兼容
成员变量无法使用
增强for中可以使用var
for(var str : list) {...}
springboot3不再兼容低版本的JDK,要求至少为JDK17
这意味着兼容springboot3的其他开源项目也开始要求更高版本的JDK,升级JDK17很有必要
此外,JDK17相比较JDK8,JDK11在性能上明显更好,值得升级
public static Stream> all() 获取可选的随机数算法列表
public static RandomGeneratorFactory of(String name) 获取给定随机数算法的RandomGeneratorFactory
public T create(long seed) 获取给定种子的RandomGenerator
default int nextInt(int bound) 获取一个bound范围内的同类型随机数
RandomGeneratorFactory.all().forEach(e->{
System.out.println(e.name());
});
//输出
L32X64MixRandom
L128X128MixRandom
L64X128MixRandom
SecureRandom
L128X1024MixRandom
L64X128StarStarRandom
Xoshiro256PlusPlus
L64X256MixRandom
Random
Xoroshiro128PlusPlus
L128X256MixRandom
SplittableRandom
L64X1024MixRandom
RandomGeneratorFactory l128X128MixRandom = RandomGeneratorFactory.of("L128X128MixRandom");
RandomGenerator randomGenerator = l128X128MixRandom.create(System.currentTimeMillis());
System.out.println(randomGenerator.nextInt(100));
对JDK提供的类进行广泛的强封装,默认情况下,开发者不再能通过反射访问非公有成员
实际上,JDK8~JDK17之间的版本已经对switch进行了多次增强
从JDK14开始,switch支持lambda编写case语句体,而且可以带返回值
Integer month = 1;
String monthStr = switch (month) {
case 1-> "一月";
default -> "未知";
};
System.out.println(monthStr);
网上很多文档说JDK17给case匹配提供了模式匹配
但经过实际测试,这个功能已经被放到JDK19,当下的JDK17已经无法使用这个功能
Object month = 1d;
switch (month) {
case Integer i -> System.out.println("这是Integer");
case Double d -> System.out.println("这是Double");
default -> System.out.println("未知");
}
Sealed关键字
一个类被Sealed修饰,将会只允许permits指定的类继承,实现类必须有final或者no-sealed修饰
为什么要用fianl修饰:为了密封类继承的安全性
public sealed class Person permits Student{
private String name;
}
public final class Student extends Person{
}
JDK17在代码执行,GC效率上相比JDK8,JDK11都有了明显提升