Java官方宣布:32位系统用户,你们被抛弃了!
Java 24 正式发布!作为 JDK 25(下一个 LTS 版本)的重要铺垫,这次更新带来了哪些令人兴奋的新特性?让我们一起探索 Java 开发的新世界!
为什么 JDK 24 如此重要?
JDK 24 是一个具有里程碑意义的版本,因为这次更新中包含的 JEP(JDK 增强提案)候选功能很有可能成为JDK 25的正式特性。而 JDK 25 将在2025 年 9 月发布,成为继 JDK 21 之后的下一个长期支持(LTS)版本。
1. 简化的 Hello World:告别繁琐语法
终于来了! Java 现在支持简单的void main()方法来打印"Hello, World"!
传统写法 vs 新写法
JDK 21 及之前的传统写法:
public class MyFirstClass {
public static void main(String[] args) {
System.out.println("Hello, World");
}
}
痛点:对于 Java 初学者来说,这种冗长的代码难以理解,特别是对那些不熟悉 Java 语法的人。
JDK 24 的新写法:
void main() {
println("Hello, World");
}
注意:这不是全新的 Java 语法——有经验的 Java 开发者仍然可以使用所有现有的语法和详细写法。
实现原理:JVM 通过隐式声明类和实例方法来实现这一功能。同时,JVM 现在会在运行时自动导入某些必需的包,减少了使用println()等实用方法时的手动命名空间声明需求。
实际应用示例
下面的程序从控制台读取用户姓名并打印问候消息:
void main() {
var name = readln();
var message = "Hello, World and " + name;
println(message);
}
如果转换为传统的 Java 代码,等价于:
import java.io.*;
import java.util.Scanner;
publicclassA {
publicstaticvoidmain(String[] args) {
Scannersc=newScanner(System.in);
Stringname= sc.nextLine();
Stringmessage="Hello, World and " + name;
System.out.println(message);
sc.close();
}
}
相关 JEP:JEP 495 - 简单源文件和实例主方法[1]
2. 原始类型模式匹配:instanceof 和 Switch 的新玩法
解决的问题
JDK 21 的限制:类型匹配要求被比较的变量必须是引用类型,而不能是原始类型。
JDK 24 的改进:从 JDK 24 开始,instanceof和switch-case中的类型匹配将允许对象与原始类型匹配,而不仅仅是引用类型。
instanceof 示例
public classTest {
publicstatic String identifyType(Object value) {
if (value instanceofint) {
return String.format("int: %d", value);
} elseif (value instanceof String) {
return String.format("String: %s", value);
} elseif (value instanceof Double) {
return String.format("Double: %f", value);
} else {
return"Unknown type";
}
}
}
Switch-Case 示例
String identifyType(Object value) {
return switch (value) {
case int i -> String.format("int: %d", i); // 原始类型!
case Double d -> String.format("Double: %f", d);
case String s -> String.format("String: %s", s);
default -> "Unknown type";
};
}
相关 JEP:JEP 488 - 模式中的原始类型[2]
3. 灵活的构造函数体:突破 super() 限制
新特性:开发者现在可以在构造函数体中使用super()初始化父类之前包含逻辑代码。
JDK 21 的限制:这是不可能的——开发者必须在父类中使用辅助方法来在初始化后执行逻辑。
构造函数的新结构
构造函数体现在分为两部分:序言(Prologue)和尾声(Epilogue)。
public class A extends B {
public A() {
// 序言 - 可以在 super() 之前执行逻辑
super();
// 尾声 - super() 之后的逻辑
}
}
重要限制:在序言阶段,无法访问正在初始化的当前实例。
实际应用示例
public classAextendsB {
privatestaticintmultiplier=10;
privatefinalint childValue;
publicA(int baseValue) {
// 序言 - 计算逻辑
intcomputedValue= baseValue * multiplier;
super(baseValue); // 初始化父类 B
// 尾声 - 设置子类属性
this.childValue = computedValue;
}
}
相关 JEP:JEP 492 - 灵活的构造函数体[3]
4. 作用域值:ThreadLocal 的完美替代品
解决ThreadLocal的三大痛点
ScopedValue API 是对ThreadLocal API 的改进,用于在不同线程(包括虚拟线程)和任务之间共享不可变数据。
ScopedValue 解决的三个关键挑战:
- 可变性问题:ThreadLocal 中,线程既可以访问又可以修改共享变量,导致意外副作用。ScopedValue 只允许共享不可变数据。
- 无界生命周期:ThreadLocal 变量必须手动移除。ScopedValue 在原始拥有线程完成执行后自动清理。
- 昂贵的继承:ThreadLocal 变量必须为子线程复制和重新创建。ScopedValue 允许父子线程之间高效共享内存。
使用示例
static final ScopedValue<String> USERNAME = ScopedValue.newInstance();
void main(String[] args) {
ScopedValue.where(USERNAME, "Amrit").run(() -> {
System.out.println("主任务中的值:" + USERNAME.get());
performSubTask();
});
}
static void performSubTask() {
System.out.println("子任务中的值:" + USERNAME.get());
}
相关 JEP:JEP 487 - 作用域值[4]
5. 模块导入声明:告别重复导入
批量导入的新方式
新特性:用户现在可以直接导入一组相关包,而不是单独导入它们。
这减少了冗长性,并消除了重复包导入造成的低效率。
对比示例
传统方式:
import javax.xml.*;
import javax.xml.parsers.*;
import javax.xml.stream.*;
新方式:
import module java.xml;
其他可用模块:java.base、java.desktop、java.sql等,每个模块都为特定用例分组了所需的包。
相关 JEP:JEP 494 - 模块导入声明[5]
6. 结构化并发:并发编程的新范式
解决并发编程的结构化问题
JDK 24 引入的StructuredTask API 将并发编程中的子任务组合在一起,在运行时将它们视为一个单元,而不是独立的任务。
ExecutorService 的问题:使用传统的 ExecutorService API,子任务与启动它们的父任务只有逻辑关系,在运行时独立运行,没有直接连接。
StructuredTask 的优势:开发者现在可以控制整个任务,该任务可以由在不同任务中运行的子任务组成为一个整体单元。如果一个任务失败,失败会传播到其他依赖任务,整个任务也会中止。
代码对比示例
import java.util.concurrent.*;
Integer fun1()throws Exception {
Integerval=1;
for (inti=0; i < 10; i++) {
println(val);
val++;
Thread.sleep(1000);
if (val == 4) {
System.out.println("Fun 1 在值为 4 时停止");
thrownewException();
}
}
return val;
}
Integer fun2()throws InterruptedException {
Integerval=1;
for (inti=0; i < 10; i++) {
println(val);
val++;
Thread.sleep(1000);
}
return val;
}
// 使用 StructuredTask API
voidhandle()throws ExecutionException, InterruptedException {
try (varscope=newStructuredTaskScope.ShutdownOnFailure()) {
// 使用作用域分组
Supplier<Integer> x = scope.fork(() -> fun1());
Supplier<Integer> y = scope.fork(() -> fun2());
scope.join().throwIfFailed();
} catch (Exception e) {
println("Fun 1 和 Fun 2 都已停止,因为 Fun 1 失败了");
}
}
// 传统 ExecutorService 方式
voidhandleWithoutST()throws ExecutionException, InterruptedException {
ExecutorServiceexsc= Executors.newFixedThreadPool(3);
Future<Integer> x = exsc.submit(() -> fun1());
Future<Integer> y = exsc.submit(() -> fun2());
exsc.shutdown();
}
相关 JEP:JEP 499 - 结构化任务[6]
7. AOT 类加载和链接:启动速度提升 40%
性能革命性提升
提前(AOT)类加载和链接旨在改善 Java 应用程序的启动时间。
实现原理:通过在一次运行期间缓存类的加载和链接形式,并在后续运行中重用它们来实现这一点。
这一增强还为启动和预热时间的未来优化奠定了基础。
性能提升:提前编译使 Java 程序性能提升了40%!
相关 JEP:JEP 483 - AOT 类加载和链接[7]
8. 告别 32 位:移除 Windows 32 位支持
平台支持的重要变化
Java 的核心理念一直是"一次编译,处处运行"——只要有 JVM,就能编译运行。但随着 JDK 24 正式移除对 Windows 32 位系统的支持,这个经典承诺需要加上一个重要前提:目标平台仍在官方支持范围内。JDK 24 正式移除了对 Windows 32 位系统的支持,这是 Java 平台演进的一个重要里程碑。
重要提醒:如果你还在使用 Windows 32 位系统,必须迁移到 64 位系统才能使用 JDK 24 及以后的版本。(PS 笔者最近还真见过在 32 位系统上搞Java应用开发的)
相关 JEP:JEP 479 - 移除 Windows 32 位 x86 端口[8]
引用链接
[1] JEP 495 - 简单源文件和实例主方法:
https://openjdk.org/jeps/495
[2]JEP 488 - 模式中的原始类型:
https://openjdk.org/jeps/488
[3]JEP 492 - 灵活的构造函数体:
https://openjdk.org/jeps/492
[4]JEP 487 - 作用域值:
https://openjdk.org/jeps/487
[5]JEP 494 - 模块导入声明:
https://openjdk.org/jeps/494
[6]JEP 499 - 结构化任务:
https://openjdk.org/jeps/499
[7]JEP 483 - AOT 类加载和链接:
https://openjdk.org/jeps/483
[8]JEP 479 - 移除 Windows 32 位 x86 端口:
https://openjdk.org/jeps/479
相关文章
- Java官方宣布:32位系统用户,你们被抛弃了!
- Java二十周年特别策划--谈谈我与Java的那些年、这些事
- Java二十周年特别策划——谈谈我与Java的那些年、这些事
- Java 25 在 JEP 519 中集成了紧凑对象头
- Java动态代理
- JAVA入门教程-第1章 概述
- 那些让你望而却步的Java概念,其实没那么难!
- CBN x ASEAN Watch丨Labubu-mania: The unlikely cultural sensation sweeping Southeast Asia
- CBN Correspondent丨Coffee shirt, methanol bus, 100% green power…Boao goes all-in on zero-carbon push
- CBN丨Policy supports to shore up foreign investors' confidence