从Java8升级到Java17新增了哪些比较受欢迎的新特性

从Java8升级到Java17新增了什么


Java现在发布的版本很快,每年两个,但是真正会被大规模使用的是3年一个的LTS版本。

这也是为什么你会发现Java9、Java13...这些版本都很少被人提起的原因

每 3 年发布一个 LTS(Long-Term Support),长期维护版本。意味着只有 Java 8 Java 11 Java 17 Java 21 才可能被大规模使用

如果你像我一样,已经使用了很长时间的Java 8,并且觉得自己需要学习Java的新功能,那么这篇文章就是为你准备的。

从Java8开始,有许许多多的新功能被添加到了JDK中,但是很明显不是所有的功能都有用,好用,受大家的欢迎。

所以,我在本文中列出了从Java8开始较受Java程序员欢迎的功能

1.Local Variable Type Inference[局部变量类型推断]

局部变量类型推断 可以说是Java8以来添加的最受欢迎的功能了,它允许你在不指定类型的情况下声明局部变量。实际代码执行时候的类型是通过表达式右侧的内容推断出来的,该功能也称之为var类型。(感觉就是把 JavaScript 抄过来,个人不太喜欢这个新特性)

Java8 使用局部变量

ini 复制代码
URL url = new URL("https://www.baidu.com");
System.out.println(url.getClass());

Java10 有了局部变量类型推断后

ini 复制代码
var url = new URL("https://www.baidu.com");
System.out.println(url.getClass());

上面的代码最终的输出是完全一样的,但是很明显,在Java10以后不需要声明具体的局部变量类型。

个人感觉 var 并不好,有时候声明了并不会赋值,在开发、调试或者其他时候,看到代码并不知道他到底是什么类型和什么作用,个人还是觉得能写全最好

2.switch expression[switch表达式增强]

在Java 14中使用switch表达式时,你不必使用break关键字来跳出switch语句,也不必在每个switch case上使用return关键字来返回一个值;相反,你可以返回整个switch表达式。这种增强的switch表达式使整个代码看起来更干净,更容易阅读。

Java8中使用switch

csharp 复制代码
int flag = 1;
switch(flag) {
    case 1:
        System.out.println("hello");
        break;
    case 2:
        System.out.println("world");
        break;
    case 3:
        System.out.println("hello world");
        break;
    case 4:
        System.out.println("hello");
        break;
    default:
        System.out.println("haha");
}

Java14后使用switch

csharp 复制代码
int flag = 1;
switch(flag) {
    case 1,4 -> System.out.println("hello");
    case 2 -> System.out.println("world");
    case 3 -> System.out.println("hello world");
    default -> System.out.println("haha");
}

3.Text blocks[文本块]

文本块是Java 15中出现的一个新特性,它允许你在不使用转义符号的情况下创建多行字符串。在代码中写Json并且还想换行的时候就非常舒服。通过下面的例子,你可以看到如果使用了文本块,代码会变得多么的简洁和舒服。

Java8中

swift 复制代码
String json = "{\n" +
        "  "id": 3,\n" +
        "  "username": "fake_data",\n" +
        "  "password": "fake_data",\n" +
        "  "ips": [\n" +
        "    "fake_data"\n" +
        "  ],\n" +
        "  "firstLoginTime": 29,\n" +
        "  "lastLoginTime": 69,\n" +
        "  "failedAttempts": 62,\n" +
        "  "lockedUntil": "2013-11-20 20:23:23"\n" +
        "}";

Java15之后

arduino 复制代码
String json = """
    {"id": 3, 
    "username": "fake_data", 
    "password": "fake_data", 
    "ips": ["fake_data"], 
    "firstLoginTime": 29, 
    "lastLoginTime": 69, 
    "failedAttempts": 62, 
    "lockedUntil": "2013-11-20 20:23:23"}
""";

4.Records[record类]

record类是Java14引入的一个新的声明类的方式(之前之后class)。通过该关键字你可以用更少的代码创建一个类似于POJO的类(害,就是个普通的Java类,譬如 User类,Student类等,或者叫实体类也行,不需要分的很细致)。相较于以往,在此之前大多数开发者使用Lombok来简化POJO类的写法(不需要写get set之类),但现在,使用了record,你不需要使用任何第三方库,就可以将代码写的更加简洁。在下面的例子中,你可以看到用record代码会多么的简洁。

Java8

typescript 复制代码
public class User {
    private String name;
    private String password;

    public User() {

    }
    
    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

Java8使用lombok

less 复制代码
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
    private String name;
    private String password;
}

使用record

arduino 复制代码
public record User(String name,String password) {}

老实说,还是喜欢用lombok,record虽然好,但是感觉无法很直观的看得到我声明的 属性

5.Sealed classes[密封类]

封闭类是Java 17中加入的一个新特性。它允许你将一个类或接口的继承限制在一组有限的子类中。简单来说就是,你有一个 UserService接口,只想要被 UserServieImpl 实现,以前是不能限制的,现在有了Sealed classes特性之后就可以了,那么具体如何做到呢?

通过 sealed 修饰符来描述某个类为密封类,同时使用 permits 关键字来制定可以继承或实现该类的类型有哪些。注意 sealed 可以修饰的是类(class)或者接口(interface),所以 permits 关键字的位置应该在 extends 或者 implements 之后。

例子:

使用sealed声明一个UserService只能够被UserServiceImpl,UserServiceFinalImpl实现。

kotlin 复制代码
kotlin
复制代码public sealed interface UserService permits UserServiceImpl, UserServiceFinalImpl{
}

想要实现sealed声明的接口(继承类也一样),子类,或者实现类,需要用final或者non-sealed修饰。

java 复制代码
java
复制代码public final class UserServiceFinalImpl implements UserService{
}

public non-sealed class UserServiceImpl implements UserService{
}

6.Useful NullPointerException

NullPointerExceptions是Java 14中加入的一个新功能。它允许你获得更多关于NullPointerExceptions的信息。

这在你调试NullPointerExceptions时非常有用。在下面的例子中,你可以看到同样的代码在Java 8和Java 14中产生了不同的

NullPointerExceptions,但在Java 14中,你可以得到更多关于异常的信息**(看到更多的异常栈信息,能够更好的进行bug定位)**

7.虚拟线程 - VirtualThread

谈论一下Java21正式发布了的虚拟线程VirtualThread

首先想说一下为什么需要有虚拟线程,虚拟线程我理解为对标GO的协程的这个概念,专门针对高并发场景而生

虚拟线程是一种在JVM层面实现的逻辑线程,并不会直接和操作系统的物理线程一一对应,可用减少上下文切换的性能开销

操作系统线程、普通线程(Java 线程)和虚拟线程的关系如下:

虚拟线程的主要用途和优势包括:

提高系统并发性能:通过减少创建和管理大量线程的开销,可以轻松构建高并发、大规模并行处理的应用程序。

简化并发编程:开发者可以创建更多的并发执行单元,无需过于担心资源消耗问题,从而更专注于业务逻辑。

更好的硬件资源利用:虚拟线程在底层仍然映射到操作系统的线程上,但JVM会更加智能地调度线程,以充分利用现代多核CPU资源。

相关推荐
小码哥_常28 分钟前
别再被误导!try...catch性能大揭秘
后端
无巧不成书02182 小时前
30分钟入门Java:从历史到Hello World的小白指南
java·开发语言
苍何3 小时前
30分钟用 Agent 搓出一家跨境网店,疯了
后端
ssshooter3 小时前
Tauri 2 iOS 开发避坑指南:文件保存、Dialog 和 Documents 目录的那些坑
前端·后端·ios
追逐时光者3 小时前
一个基于 .NET Core + Vue3 构建的开源全栈平台 Admin 系统
后端·.net
程序员飞哥3 小时前
90后大龄程序员失业4个月终于上岸了
后端·面试·程序员
zs宝来了4 小时前
Playwright 自动发布 CSDN 的完整实践
java
Cyeam4 小时前
爆火的 OpenClaw,赢在生态创新
程序员·开源·openai
吴声子夜歌5 小时前
TypeScript——基础类型(三)
java·linux·typescript
GetcharZp5 小时前
Git 命令行太痛苦?这款 75k Star 的神级工具,让你告别“合并冲突”恐惧症!
后端