技术博客 技术博客
  • JAVA
  • 仓颉
  • 设计模式
  • 人工智能
  • Spring
  • Mybatis
  • Maven
  • Git
  • Kafka
  • RabbitMQ
  • RocketMQ
  • Redis
  • Zookeeper
  • Nginx
  • 数据库套件
  • MySQL
  • Elasticsearch
  • MongoDB
  • Hadoop
  • ClickHouse
  • Hbase
  • Hive
  • Flink
  • Flume
  • SQLite
  • linux
  • Docker
  • Jenkins
  • Kubernetes
  • 工具
  • 前端
  • AI
GitHub (opens new window)
  • JAVA
  • 仓颉
  • 设计模式
  • 人工智能
  • Spring
  • Mybatis
  • Maven
  • Git
  • Kafka
  • RabbitMQ
  • RocketMQ
  • Redis
  • Zookeeper
  • Nginx
  • 数据库套件
  • MySQL
  • Elasticsearch
  • MongoDB
  • Hadoop
  • ClickHouse
  • Hbase
  • Hive
  • Flink
  • Flume
  • SQLite
  • linux
  • Docker
  • Jenkins
  • Kubernetes
  • 工具
  • 前端
  • AI
GitHub (opens new window)
  • JAVA

    • 基础

      • JAVA 锁 及 线程
      • JAVA NIO API
      • JVM 模块介绍
    • 版本

      • JAVA8 新特性总结
      • JAVA9 新特性总结
      • JAVA 10/11/12/13/14/15/16/17 新特性总结
        • JAVA 10
          • 局部变量类型推断
        • JAVA 11
          • 用于Lambda的形参局部变量语法
          • 针对String类的方法增强
          • 全新的HttpClient使用
        • java12
          • 新的switch语法
        • java13
          • 文本块
        • java14
          • 新的 instanceof 语法
          • 空指针异常的改进
          • 记录类型 Record
        • java17
          • 密封类型
    • 其他

      • jar 打包成.exe可执行文件
      • java代码混淆之 ProGuard
      • JAVA 性能监控(jvisualvm)及测试(JMeter)
      • Alibaba Arthas
      • jar启动脚本
  • 仓颉

    • 基础

      • 仓颉介绍
  • 设计模式

    • 代理模式
  • 人工智能

    • 线性回归
    • Pytorch
目录

JAVA 10/11/12/13/14/15/16/17 新特性总结

# JAVA 10

# 局部变量类型推断

在 java 中,我们可以使用自动类型推断

    public static void main(String[] args) {
        var a = "hello world";
        System.out.println("a = " + a);
    }
1
2
3
4

但是注意,var 关键字必须位于有初始值设定的变量上,否则编译都不会通过。java 终究不像 JS 那样进行动态推断,这种类型推断仅仅发生在编译期间,到最后编译完成还是会变成具体类型的。

var 关键字不能做为属性或成员变量使用,只能做为局部变量使用。

# JAVA 11

Java11 是继 Java8 之后的又一个 TLS 长期维护版本,在 Java 17 出现之前,一直都是此版本做为广泛使用的版本,其中比较关键的是用于 Lambda 的形参局部变量语法。

# 用于 Lambda 的形参局部变量语法

在 Java10 我们认识了 var 关键字,它能够让局部变量自动进行类型推断,不过它不支持在 lambda 中使用,所以在 Java11 终于支持了。

    public static void main(String[] args) {
        Consumer<String> consumer = (var s) -> System.out.println(s.length());
        consumer.accept("你好");
    }
1
2
3
4

# 针对 String 类的方法增强

    public static void main(String[] args) {
        var str = "AB\nC  \nD  ";
        // 判断是否字符串为空或者仅包含空格
        System.out.println(str.isBlank());
        str
                // 根据字符串中的 \n 换行符进行切割,分为多个字符串,并转换为Stream进行操作
                .lines()
                .forEach(System.out::println);

        // 根据传入次数,复制原有字符串并拼接到末尾 "AB\nC\nDAB\nC\nD"
        System.out.println(str.repeat(2));

        // 去除首位空格
        System.out.println(str.strip());
        // 去除首部空格
        System.out.println(str.stripLeading());
        // 去除尾部空格
        System.out.println(str.stripTrailing());
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 全新的 HttpClient 使用

在 java9 的时候其实就已经引入了全新的 HttpClient API,用于取代之前比较老的 HttpURLConnection 类,新的 API 支持最新的 HTTP2 和 WebSocket 协议。

    public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
        // 创建一个客户端
        var httpClient = HttpClient.newHttpClient();
        // 创建一个请求
        var request = HttpRequest.newBuilder(new URI("http://www.baidu.com")).GET().build();
        // 发送得到响应
        var send = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(send.body());
    }
1
2
3
4
5
6
7
8
9

# java12

java 12-16 这五个版本并非长期版本,所以很多特性都是一种处于实验性功能,12/13 版本引入了一些实验性功能,并根据反馈进行调整,最后在后续版本中正式开放使用,其实就是体验服的那种感觉。

# 新的 switch 语法

新的语法可以大大方便我们的编写,但是还是美中不足的是不能支持范围匹配

    /**
     * 传入分数
     * 90-100 优秀
     * 70-90 良好
     * 60-70 及格
     * 0-60 差
    **/
    public static String old(int score){
        score/=10;
        String str;
        switch (score){
            case 10:
            case 9:
                str = "优秀";
                break;
            case 8:
            case 7:
                str = "良好";
                break;
            case 6:
                str = "几个";
                break;
            default:
                str = "不及格";
        }
        return str;
    }

    public static String java12(int score){
        score/=10;
        return switch (score){
            case 10,9 -> "优秀";
            case 8,7 -> "良好";
            case 6 -> "几个";
            default -> "不及格";
        };
    }

    public static String java12_1(int score){
        score/=10;
        return switch (score){
            case 10,9 -> "优秀";
            case 8,7 -> "良好";
            case 6 -> "几个";
            default -> {
                System.out.println("其他方式");
                yield "不及格";
            }
        };
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

# java13

# 文本块

当我们需要使用复杂字符串时,可能字符串中包含了很多需要转移的字符,比如双引号等,这时我们就可以使用三引号来囊括字符串

    public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
        var strA = "aa";
        var s = """
                    dsafdsafdsa %s
                        dfdsafd
                            ""fdsa \n \n dsfdsa
                            \r ffff \t dsfad 
                """.formatted(strA);
        System.out.println(s);
    }

结果打印:
    dsafdsafdsa aa
        dfdsafd
            ""fdsa 
 
 dsfdsa
 ffff 	 dsfad
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# java14

# 新的 instanceof 语法

    public boolean old(Object o) {
        if (this == o) {return true;}
        if (o instanceof User) {
            User user = (User) o;
            return user.name.equals(this.name);
        }
        return false;
    }

    public boolean java16(Object o) {
        if (this == o) {return true;}
        if (o instanceof User user) {
            return user.name.equals(this.name);
        }
        return false;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 空指针异常的改进

在旧版本中如果出现空指针异常,报错只会给我们空指针发生在哪一行,具体哪个变量为空并不会告诉我们,需要我们自己打 debug,在新的版本中会明确告知我们。

# 记录类型 Record

继类、接口、枚举、注解之后的又一新类型来了,他的名字叫 记录 ,在 java14 中首次出场,这一出场,Lombok 的噩梦来了。 在实际开发中,很多类仅仅只是充当一个实体类罢了,保存的是一些不可变数据,比如我们从数据库中查询的账户信息,最后被映射为一个实体类

@Data
public class User {

    private String name;
  
    private Integer age;
}
1
2
3
4
5
6
7

Lombok 可以说时简化代码的神器,它能在编译时自动生成 get、set、构造器、toString () 方法等,在编写这些实体类时,简直不要太好用,Record 可以让我们不需要显式地定义构造函数、getters 方法或 equals 和 hashCode 方法。所有这些都会由 Records 自动生成。

记录类型本质上也是一个普通类,不过是 final 类型且继承自 java.lang.Record 抽象类的,他会在编译时,会自动编译出 get、hashCode、equals、toString 等方法。

// 只能把字段写道括号中
public record User(String name,Integer age) {
    public static void a(){
    }
    public static void main(String[] args) {
        User user = new User("张三",2);
        System.out.println(user.name());
        System.out.println(user);
    }

}
1
2
3
4
5
6
7
8
9
10
11

但有些功能还是没有办法与 Lombok 相比的,如 @SL4J,链式调用,无参构造函数不支持等。

# java17

# 密封类型

密封类型可以说时 java17 正式推出的又一重磅类型,它在 java15 首次提出并测试了两个版本。

在 java 中,我们可以通过继承(extends 关键字)来实现类的能力复用,扩展与增强。但有的时候,可能并不是所有的类我们都希望能够被继承。所以,我们需要对继承关系有一些限制的控制手段,而密封类的作用就是限制类的继承。实际上在之前我们如果不希望别人继承我们的类,可以直接添加 final 关键字。

这样有一个缺点,如果添加了 final 关键字,那么无论是谁,包括我们自己也是没办法实现继承的,但是现在我们有一个需求,只允许我们自己写的类继承,但是不允许别人写的类继承,这时该咋写?在 java17 之前想要实现就很麻烦。

# 旧版本
public final class A{
}

# 新版本 sealed
public sealed class A permits B {
}
# 继承 A
public final class B extends A {
}
public sealed class B extends A {
}
public non-sealed B extends A {
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

密封类型有以下要求:

  • 可以基于普通类、抽象类、接口,也可以继承自其他接口的子类或是实现其他接口的类等。
  • 必须有子类继承,且不能是匿名内部类或是 lambda 的形式
  • sealed 写在原来 final 的位置,但不能和 final、non-sealed 关键字同时出现,只能选其一
  • 继承的子类必须显示的标记为 final(表示这个类不能被继承)、sealed(表示这个子类也可以有其他密封的或非密封的子类) 或是 non-sealed (表示这个子类不能有子类,但它可以被其他类继承)类型
上次更新: 6/11/2025, 4:10:30 PM
JAVA9 新特性总结
jar 打包成.exe可执行文件

← JAVA9 新特性总结 jar 打包成.exe可执行文件→

Theme by Vdoing | Copyright © 2023-2025
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式