JDK11升级到JDK17在开发层面的新特性梳理

2021-04-26 by 没有评论

jdk17即将于今年9月发布,作为jdk11之后的又一个LTS版本,jdk17也会在未来作为生产环境的标配之一,那么这几年内jdk有哪些新特性呢,我们来梳理一下

考虑GC机制对普通开发者并不敏感,这里进行了省略

JDK11相对于JDK8的更新

尽管jdk17发布在即,使用jdk8的生产环境依然广泛存在,先回顾一下吧

集合加强(jdk9,jdk10,jdk11)

对所有的集合类型增加了of方法来创建静态集合

List<String> list = List.of("foo","bar");
Set<String> set = Set.of("foo","bar");

jdk10又增加了copyOf方法来复制一个不可改变集合

List<String> listA = List.of("foo","bar");
List<String> listB = List.copyOf(listA);

jdk11增加了toArray的重载方法,同时传入数组长度为0时可以自动扩充

// 旧的方法:传入String[]:
String[] oldway = list.toArray(new String[list.size()]);

// 新的方法:传入IntFunction:
String[] newway = list.toArray(String[]::new);

私有接口方法(jdk9)

可以在interface中定义private方法给default方法调用,在default方法中抽取方法又不想公开时可以这么写

IO加强(jdk9)

java.io.InputStream中新增了方法便于读取和复制其中包含的数据

  • readAllBytes: 读取所有剩余字节
  • readNBytes: 读取指定数量的字节
  • transferTo: 读取InputStream中的字节并直接写入对应的OutputStream

JShell工具(jdk9)

提供的小工具可以以控制台脚本的形式快速执行一段java表达式

Stream扩充(jdk9,jdk10)

新增了2个过程中方法:

  • dropWhile: 按顺序遍历并丢弃,Predicate第一次返回false后开始读取
  • takeWhile: 按顺序遍历并读取,Predicate第一次返回false后丢弃

注意在无序stream中可能产生不同的结果

新增两个static方法:

  • ofNullable: 对于.of(),可避免空指针错误
  • iterate: 新增异构方法,增加退出条件参数

Optional对象新增orElseThrow方法用于不存在时抛出异常

收集数据时增加了不可变集合的输出方式

list.stream().collect(Collectors.toUnmodifiableList());
list.stream().collect(Collectors.toUnmodifiableSet());

增加HttpClient实现(jdk9)

局部类型推断(jdk10,jdk11)

可以用var定义局部变量了,在jdk11中,var可用在lambda表达式中标识变量

读写文件优化(jdk11)

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 API(jdk11)

String对象新增了若干方法

  • strip: 类似trim(),但strip可去除unicode空格,如中文全角空格
  • isBlank: 判断是不是空白字符串,可以识别unicode空格
  • lines: 将文本按换行符拆分
  • repeat: 指定文本重复次数并输出

JDK17新增特性

switch表达式(jdk12,jdk13,jdk14)

优化了switch表达式

//jdk12前
switch (day) {
    case MONDAY:
    case FRIDAY:
    case SUNDAY:
        System.out.println(6);
        break;
    case TUESDAY:
        System.out.println(7);
        break;
    case THURSDAY:
    case SATURDAY:
        System.out.println(8);
        break;
    case WEDNESDAY:
        System.out.println(9);
        break;
}
//jdk12+
switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
    case TUESDAY                -> System.out.println(7);
    case THURSDAY, SATURDAY     -> System.out.println(8);
    case WEDNESDAY              -> System.out.println(9);
}
//并且可以直接返回赋值
int numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY                -> 7;
    case THURSDAY, SATURDAY     -> 8;
    case WEDNESDAY              -> 9;
};

java.text支持数字压缩格式(jdk12)

NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
String result = fmt.format(1000);
//output 1K

文本块,多行文本(jdk13)

String query = """    
                SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
                WHERE `CITY` = 'INDIANAPOLIS'
                ORDER BY `EMP_ID`, `LAST_NAME`;
               """;

FileSystems.newFileSystem方法(jdk13)

可以将文件内容视为文件系统的文件系统提供程序

nio新方法(jdk13)

java.nio.ByteBuffer定义绝对批量get和put传输连续字节序列的方法,不考虑或影响缓冲区位置

java.time更新(jdk13)

更新了日本令和纪年Reiwa

record类型

record类型作为一个劣化的class类型,类似于C++中的struct,可替代简单的java bean/pojo对象

record Point (int x, int y){}
//等效于
class Point{
    private final int x;
    private final int y;
    Point(int x,int y){
        this.x = x;
        this.y = y;
    }
    public int x(){
        return x;
    }
    public int y(){
        return y;
    }
    public boolean equals(Object o){
        //...
    }
    public int hashCode(){
        //...
    }
    public String toString(){
        //...
    }
}

instanceof优化(jdk14)

//java14前
if (obj instanceof String) {
    String s = (String) obj;
    // 使用s
}
//java14后
if (obj instanceof String s) {
    // 使用s
}else{
    //不可使用s
}

Unix-Domain Socket(jdk16)

支持基于Unix文件系统的socket,可用于同一主机的进程间通信,性能和安全性均高于TCP/IP socket

待续。。等jdk17发布再补充

标签: