Java 变得越来越像 Rust
介绍
随着编程的增强和复杂性越来越流行,许多编程语言也相互效仿。 Java 也不例外。
尽管社区内部存在问题,Rust 仍逐年赢得了开发人员的喜爱。并且有充分的理由:由于编译器,Rust 使开发人员能够避免整个类别的问题。编译器要求正确性,以至于一些开发人员开始遇到一些不安全感。
我想展示 Rust 的两个特性,这些特性是 Rust 优秀的一部分,然后将它们与 Java 的最新创新进行比较。
免责声明:我绝不声称这些 Rust 功能导致其对应功能出现在 Java 中。如果 Kotlin 和或 Scala 在实现这一点方面更具影响力,我不会感到惊讶。但我很高兴看到 Rust 功能也可以(在某种程度上)在 Java 中找到!
不可变数据(Immutable Data)
在 Rust 中,数据默认是不可变的。
rust
struct User {
// struct members are immutable
name: &'static str,
age: i32
}
fn main() {
// user and members are immutable
let user = User { name: "Bob", age: 42 };
}
如果我们希望数据是可变的,则必须显式声明它是可变的。
rust
fn main() {
let mut user = User { name: "Bob", age: 42 };
user.name = "Jim";
}
现在,一个普通的 Java 对象(又名 POJO)通常是默认可变,而且相当冗长。 Java 8 中的代码如下:
java
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public static void main(String[] args) {
User user = new User("Bob", 42);
user.setName("Jim");
System.out.println(user.getName());
}
// not to mention equals(), toString() and friends!
}
然而,多亏了现代 Java,record 类在考虑到不变性的情况下简化了这一点,并且我们的代码远没有那么冗长。以下是启用了预览的有效 Java 21 代码。
java
record User(String name, int age) {}
void main() {
final var user = new User("Bob", 42);
}
代数数据类型(Algebraic Data Types)
在这段 YouTube 视频中,我们看到 Rust 如何利用代数类型来帮助使无效状态变得不可表示,并强有力地保证防止错误行为。在 Rust 中,这是使用枚举完成的:
rust
enum RealCat {
Alive { is_hungry: bool },
Dead
}
fn main() {
let real_cat: RealCat = RealCat::Alive { is_hungry: true };
match real_cat {
RealCat::Alive { is_hungry } => {
if is_hungry {
println!("The cat demands a sacrifice.");
} else {
println!("The cat is bored.");
}
},
RealCat::Dead => println!("Oh no!!!")
}
}
直到最近,这还无法在 Java 中优雅地实现。然而,从 Java 21 及更高版本开始,您可以使用包含记录的密封接口并使用详尽的 switch 语法在 Java 中优雅地实现此功能:
RealCat.java
java
public sealed interface RealCat permits RealCat.Alive, RealCat.Dead {
record Alive(boolean isHungry) implements RealCat {}
record Dead() implements RealCat {}
static void check(RealCat realCat) {
switch (realCat) {
case Alive aliveCat -> {
if (aliveCat.isHungry()) {
System.out.println("The cat demands a sacrifice.");
} else {
System.out.println("The cat is bored.");
}
}
case Dead _ -> System.out.println("Oh no!!!");
}
}
}
RealCatApplication.java
java
void main() {
final var hungryCat = new RealCat.Alive(true);
RealCat.check(hungryCat);
}
结论
有无数(充分)的理由表明 Java 永远不会成为 Rust,但我很高兴看到 Rust 的一些强大功能进入了 Java。这将巩固 Java 作为商业世界首选编程语言之一的长期地位。 Java 在过去 28 年中一直拥有重要的市场份额,并且由于 OpenJDK 项目致力于提高开发人员的生产力,因此在未来 28 年中即使不能重新获得重要的市场份额,也有望保持这一市场份额。