八个理由:从java8升级到Java17

简介: 八个理由:从java8升级到Java17

前言

从Java 8 到 Java 20,Java 已经走过了漫长的道路,自 Java 8 以来,Java 生态系统发生了很多变化。最显着的变化是 Java 的发布节奏。Java 8 于 2014 年发布,Java 17 于 2021 年发布。这两个版本之间相隔了 7 年。Java17是一个长期支持(LTS)的版本,会有更稳定和持久的维护和更新。

1. 局部变量类型推断

这是自 Java 8 以来添加到 Java 中的最受欢迎的功能之一。它允许你在不指定类型的情况下声明局部变量。类型是从表达式的右侧推断出来的。此功能也称为var类型。

var name = "John"; // 推断name的类型为String
var age = 25; // 推断age的类型为int
 
System.out.println(name); // 输出:John
System.out.println(age); // 输出:25

需要注意的是,var类型的局部变量仍然具有静态类型,一旦被推断出来,类型就会固定下来,并且不能重新赋值为不兼容的类型。

2.switch表达式

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

来看一个需求:根据不同的月份,返回相应的季节名称。

传统java8

int month = 9;
String season;
 
switch (month) {
    case 12:
    case 1:
    case 2:
        season = "Winter";
        break;
    case 3:
    case 4:
    case 5:
        season = "Spring";
        break;
    case 6:
    case 7:
    case 8:
        season = "Summer";
        break;
    case 9:
    case 10:
    case 11:
        season = "Autumn";
        break;
    default:
        throw new IllegalArgumentException("Invalid month: " + month);
}
 
System.out.println(season); // 输出:Autumn
 

java14switch表达式用法

int month = 9;
 
String season = switch (month) {
    case 12, 1, 2 -> "Winter";
    case 3, 4, 5 -> "Spring";
    case 6, 7, 8 -> "Summer";
    case 9, 10, 11 -> "Autumn";
    default -> throw new IllegalArgumentException("Invalid month: " + month);
};
 
System.out.println(season); // 输出:Autumn

Java 14还引入了新的关键字yield,用于从switch表达式中返回一个值。使用yield可以提高代码的可读性,并且可以在一个case块中计算多个结果

String season = switch (month) {
    case 12, 1, 2 -> {
        yield "Winter";
    }
    case 3, 4, 5 -> {
        yield "Spring";
    }
    case 6, 7, 8 -> {
        yield "Summer";
    }
    case 9, 10, 11 -> {
        yield "Autumn";
    }
    default -> throw new IllegalArgumentException("Invalid month: " + month);
};

3.文本块

文本块是 Java 15 中添加的一项新功能。它允许你在不使用转义序列的情况下创建多行字符串。这在你创建 SQL 查询或 JSON 字符串时非常有用。在下面的示例中,你可以看到使用文本块时代码看起来更加简洁。

4.Records

记录Records是添加到 Java 14 的一项新功能。它允许你创建用于存储数据的类。它类似于 POJO 类,但代码少得多;大多数开发人员使用 Lombok 生成 POJO 类,但是有了记录,你就不需要使用任何第三方库。在下面的对比示例中,你可以看到创建记录类所需的代码非常少。

传统java8

public class Person {
    private String name;
    private int age;
 
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
 
    //getter,setter,equaes,hashCode..........
 
}

使用 Lombok

import lombok.Data;
 
@Data
public class Person {
    private String name;
    private int age;
}

java14Records

public record Person(String name, int age) {
 
}

需要注意的当使用记录类时,字段被声明为final,因此它们的值在对象创建后不能被修改。如果你尝试直接修改记录类的字段值,编译器会报错。它适用于那些不需要在运行时修改的不变数据类。

5.模式匹配instanceof

模式匹配instanceof是 Java 16 中添加的一项新功能。它允许你将instanceof运算符用作返回已转换对象的表达式。当你使用嵌套的 if-else 语句时,这非常有用。在下面的示例中,你可以看到我们如何使用instanceof运算符来捕获Employee对象,而不是进行显式转换。

6. 密封类

密封类是添加到 Java 17 中的一项新功能。它允许你将类或接口的继承限制为一组有限的子类。当你想将类或接口的继承限制为一组有限的子类时,这非常有用。在下面的示例中,你可以看到我们如何使用sealed关键字将类的继承限制为一组有限的子类。

你可以通过在类的声明前加上sealed关键字来将该类声明为密封类。然后,你可以使用permits关键字列出该密封类允许继承的子类。这些子类必须直接或间接地继承自密封类。这样,只有在这个预定义的子类中,才能继承该密封类

//使用permits关键字列出了允许继承的子类Circle、Rectangle和Triangle
public sealed class Shape permits Circle, Rectangle, Triangle {
    // 省略实现
}
 
final class Circle extends Shape {
    // 省略实现
}
 
final class Rectangle extends Shape {
    // 省略实现
}
 
final class Triangle extends Shape {
    // 省略实现
}

7. HttpClient

Java 11 引入了一个新的标准 HTTP 客户端 API,名为 HttpClient。这个 API 提供了一种现代化和灵活的方式来进行网络通信,相对于以前的 HttpURLConnection,它更易于使用和扩展,也提供了更强大的功能

// 创建 HttpClient 实例
HttpClient httpClient = HttpClient.newHttpClient();
 
// 创建 HttpRequest 实例
HttpRequest httpRequest = HttpRequest.newBuilder()
        .uri(URI.create("https://example.com"))
        .build();
 
// 发送 GET 请求并获取响应
HttpResponse<String> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
 
// 输出响应内容
System.out.println(httpResponse.body());

8.性能和内存管理能力提高

Java 17 引入了两个新的垃圾回收器算法:ZGC 和 Shenandoah,并对现有的 G1 垃圾回收器进行了一些优化和改进,提高了性能和内存管理。

ZGC

ZGC 是一个低延迟、可扩展的垃圾回收器,它的设计目标是在几毫秒甚至是亚毫秒级别内完成垃圾回收操作。ZGC 能够处理非常大的堆内存,最大支持 16TB 的堆内存大小。

ZGC 使用了不同于传统垃圾回收器的分代模型,它将整个堆内存划分为若干个连续的内存区域,称为「任意内存区间」(Arbitrary Memory Ranges,AMRs),并将每个 AMR 都视为独立的对象组。这种设计可以让 ZGC 更好地处理非连续内存分配和释放操作,从而避免了传统分代垃圾回收器中可能出现的内存碎片问题。

ZGC 还使用了一些高级技术,如并发线程根扫描、无需暂停的对象分配、指针压缩等,以提高垃圾回收的效率和性能。

Shenandoah

Shenandoah 是另一个低延迟、可扩展的垃圾回收器,它的设计目标也是在几毫秒内完成垃圾回收操作。Shenandoah 采用了一种类似于 ZGC 的划分方式,将整个堆内存划分为若干个连续的内存区域,并使用读屏障和写屏障等技术来保证垃圾回收的正确性。

Shenandoah 还支持多个并发垃圾回收线程,可以在多核 CPU 上充分利用硬件资源,提高垃圾回收的效率。

G1 垃圾回收器优化

Java 17 还对现有的 G1 垃圾回收器进行了一些优化和改进,提高了性能和内存管理。具体来说,包括以下方面:

  • 改进了 G1 的堆内存分配策略,避免了大量的内存浪费;
  • 引入了一种新的内存池机制,能够更好地利用堆内存空间;
  • 对 G1 的日志记录机制进行了改进,可以更快地诊断和修复内存问题;
  • 改进了 G1 的垃圾回收算法,能够更好地处理大型应用程序和大型堆内存。
目录
相关文章
|
24天前
|
编解码 Oracle Java
java9到java17的新特性学习--github新项目
本文宣布了一个名为"JavaLearnNote"的新GitHub项目,该项目旨在帮助Java开发者深入理解和掌握从Java 9到Java 17的每个版本的关键新特性,并通过实战演示、社区支持和持续更新来促进学习。
63 3
|
3月前
|
Java
【思维导图】JAVA网络编程思维升级:URL与URLConnection的逻辑梳理,助你一臂之力!
【思维导图】JAVA网络编程思维升级:URL与URLConnection的逻辑梳理,助你一臂之力!
49 1
|
18小时前
|
SQL Java OLAP
java实现“数据平滑升级”
java实现“数据平滑升级”
16 2
|
1天前
|
SQL Java OLAP
java实现“数据平滑升级”
java实现“数据平滑升级”
5 0
|
16天前
|
Java 编译器 API
从Java 8到Java 17,这些新特性让你的代码起飞!
【10月更文挑战第10天】在软件开发领域,Java作为一种历史悠久且广泛使用的编程语言,不断进化以适应新的需求和挑战。从Java 8到Java 17,每一次版本更新都带来了诸多新特性和改进,极大地提升了开发效率和代码质量。今天,我们就来一起探讨这些新特性,看看它们是如何让我们的代码“起飞”的。
89 0
|
2月前
|
Oracle Java 关系型数据库
【颠覆性升级】JDK 22:超级构造器与区域锁,重塑Java编程的两大基石!
【9月更文挑战第6天】JDK 22的发布标志着Java编程语言在性能和灵活性方面迈出了重要的一步。超级构造器和区域锁这两大基石的引入,不仅简化了代码设计,提高了开发效率,还优化了垃圾收集器的性能,降低了应用延迟。这些改进不仅展示了Oracle在Java生态系统中的持续改进和创新精神,也为广大Java开发者提供了更多的可能性和便利。我们有理由相信,在未来的Java编程中,这些新特性将发挥越来越重要的作用,推动Java技术不断向前发展。
|
3月前
|
设计模式 算法 Java
【揭秘】如何巧妙运用Java模板方法模式,让你的代码优雅升级?
【8月更文挑战第30天】模板方法模式是一种行为型设计模式,它定义了算法的骨架并将某些步骤延迟到子类中,使子类能在不改变算法结构的情况下重定义特定步骤。此模式适用于具有共同结构但细节不同的场景,如角色升级系统。通过定义一个抽象类 `Character` 包含模板方法 `levelUp` 和抽象步骤方法,子类如 `Warrior` 和 `Mage` 可以实现具体逻辑。这种方式提供了良好的扩展性,确保算法结构不变,同时保持系统的稳定性和一致性,在数据处理和业务流程管理中广泛应用。
52 2
|
3天前
|
监控 安全 Java
在 Java 中使用线程池监控以及动态调整线程池时需要注意什么?
【10月更文挑战第22天】在进行线程池的监控和动态调整时,要综合考虑多方面的因素,谨慎操作,以确保线程池能够高效、稳定地运行,满足业务的需求。
71 38
|
1天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?
|
5天前
|
Java 调度
[Java]线程生命周期与线程通信
本文详细探讨了线程生命周期与线程通信。文章首先分析了线程的五个基本状态及其转换过程,结合JDK1.8版本的特点进行了深入讲解。接着,通过多个实例介绍了线程通信的几种实现方式,包括使用`volatile`关键字、`Object`类的`wait()`和`notify()`方法、`CountDownLatch`、`ReentrantLock`结合`Condition`以及`LockSupport`等工具。全文旨在帮助读者理解线程管理的核心概念和技术细节。
18 1
[Java]线程生命周期与线程通信