你好,经验丰富的 Java 开发者!
欢迎来到这个全新的专栏。我知道你,你可能已经在 Java 的世界里游刃有余了。你熟悉 JVM 的每一个角落,玩得转 Spring 全家桶,能随手写出漂亮的 Lambda 表达式,也能在 Maven 或 Gradle 的 pom.xml
和 build.gradle
文件中挥斥方遒。这是一个温暖、生态繁荣且无比强大的“舒适区“。
那么,问题来了:我们为什么还要“自讨苦吃”,来学习一门以“陡峭的学习曲线”而闻名的新语言——Rust 呢?
答案很简单:为了获得一种新的“超能力”。
学习 Rust 并不意味着要抛弃 Java。Java 在企业级应用、大型系统和快速开发方面依然是无可替代的王者。学习 Rust,是为了给你的工具箱里,添加一件削铁如泥的“神兵利器”。当你遇到以下场景时,这件兵器将让你所向披靡:
- 追求极致性能: 当你需要编写性能敏感的模块,比如网络代理、游戏引擎、高性能计算,或者任何不希望被 GC 停顿(GC Pause)打扰的场景。
- 保证绝对安全: 当你需要编写系统底层软件、嵌入式程序,或者任何一个微小的内存错误都可能导致灾难性后果的场景。
- 拥抱现代并发: 当你想自信地编写多线程代码,而又不必担惊受怕地使用
synchronized
、volatile
和处理ConcurrentModificationException
。
Rust 的核心承诺就是这三点:性能、安全、并发。它通过一套独特的设计哲学,让你在编写代码时就能拥有这些优势,而不是等到运行时才去祈祷不要出问题。
心动了吗?让我们放下高谈阔论,卷起袖子,亲自感受一下 Rust 的脉搏。
第一步:搭建你的 Rust “锻造炉”
与 Java 需要安装 JDK 类似,我们需要安装 Rust 的工具链。但过程可能比你想象的要简单得多。Java 生态的开发者可能熟悉 SDKMAN!
,Rust 有一个类似的、也是官方推荐的工具,叫做 rustup
。
打开你的终端(Linux/macOS)或 PowerShell(Windows),运行以下命令:
curl --proto '=httpshttps' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup
会为你安装所有需要的东西,主要包括:
rustc
:Rust 的编译器,相当于javac
。cargo
:Rust 的项目管理和构建工具,可以把它想象成 Maven + Gradle + NPM 的超集。它负责依赖管理、编译、测试、文档生成等一切事务。rust-std
:Rust 的标准库,类似 Java 的rt.jar
。
安装完成后,你的 Rust “锻造炉”就准备就绪了。cargo
将是我们未来最常打交道的伙伴。
第二步:“Hello, world!”——Cargo 的初次献艺
在 Java 中,我们要写一个 “Hello, World!",通常会创建一个 HelloWorld.java
文件。在 Rust 中,我们让 cargo
来为我们打理一切。
在终端里执行:
cargo new hello_world
这个命令会创建一个名为 hello_world
的新目录,结构如下:
hello_world/
├── Cargo.toml
└── src/
└── main.rs
Cargo.toml
:这是一个清单文件(Manifest File),使用 TOML 格式。它就是我们项目的“pom.xml
”或“build.gradle
”,用于定义项目元数据、依赖项等。src/main.rs
:这便是我们的源代码文件。.rs
是 Rust 源代码文件的后缀。
让我们看看 src/main.rs
里的内容,cargo
已经为我们生成了经典的 “Hello, World!” 代码:
fn main() {
println!("Hello, world!");
}
现在,让我们运行它。忘掉 javac
再 java
的两步走吧。在 hello_world
目录下,只需一个命令:
cargo run
你的终端会显示:
Compiling hello_world v0.1.0 (/path/to/your/hello_world)
Finished dev [unoptimized + debuginfo] target(s) in 0.50s
Running `target/debug/hello_world`
Hello, world!
看到了吗?cargo
自动完成了编译(Compiling)和运行(Running)两个步骤。简洁,高效。
第三步:思想冲击——解构 fn main()
现在,让我们把目光聚焦在这短短的三行代码上,并用我们 Java 的“肌肉记忆”来审视它:
fn main() {
println!("Hello, world!");
}
对比一下 Java 的版本:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}
Java 开发者会立刻产生一连串的疑问:
class
去哪了?public static void
这些关键字都去哪了?println!
后面为什么有个感叹号!
?
这正是我们从 Java 到 Rust 的第一个思想转变的开始。
fn main()
:fn
是 Rust 中声明函数(function)的关键字。main
函数是程序的入口,这一点和 Java 一样。它没有参数,因为我们这个程序不需要接收命令行参数。- 没有
class
:Rust 不是一门像 Java 那样的传统面向对象(OOP)语言。它有struct
(结构体)来封装数据,有impl
(实现块)来定义方法,但它没有“类”这个概念。main
函数在 Rust 中是一个独立的函数,不隶属于任何结构体。 - 没有
public static void
:public
:在 Rust 中,所有东西默认都是私有的(private)。如果想让函数或结构体等对外可见,需要使用pub
关键字。但main
函数是程序的入口,它天生就是“公开”的,无需额外声明。static
:Java 的main
方法是静态的,因为它需要在没有创建类的实例的情况下被 JVM 调用。Rust 的函数模型不同,函数本身就是一等公民,不依赖于某个实例存在,所以自然也就不需要static
这个概念来修饰。void
:在 Rust 中,如果一个函数不返回任何值,它会隐式地返回一个叫做“单元类型(unit type)”的东西,写作()
。所以,fn main()
等价于fn main() -> ()
。这体现了 Rust 的一个核心思想:万物皆表达式(Everything is an expression),我们后面会深入探讨。
println!
:这个!
标志着println
不是一个普通的函数,而是一个宏(Macro)。你可以暂时把它理解为一种“代码模板”,它能在编译期生成更复杂的代码。Java 开发者可以类比 LOMBOK 的@Getter
/@Setter
注解,它们也是在编译期为你生成get
/set
方法。println!
宏之所以强大,是因为它可以接收可变数量的参数,并进行格式化输出,这是普通函数难以做到的。
第四步:终极拷问——我的 GC 去哪了?
好了,程序运行成功,语法也初步了解了。现在,让我们回到本章标题提出的那个核心问题。
当我们运行 cargo run
时,它在 target/debug/
目录下生成了一个名为 hello_world
的可执行文件。这是一个原生的、独立的二进制文件。你可以直接运行它,不需要任何虚拟机(VM)。
没有 JVM!
这个事实引出了一个令所有 Java 开发者感到既兴奋又困惑的问题:如果连 JVM 和它附带的垃圾回收器(Garbage Collector, GC)都没有了,那内存是谁在管理?
在 Java 中,我们随心所欲地 new
对象,然后就撒手不管了。GC 会在后台默默地扫描,找到那些不再被引用的对象,然后回收它们占用的内存。我们为此付出的代价是:GC 本身的性能开销,以及偶尔发生的、让人头疼的“Stop-The-World”GC 停顿。
在 C/C++ 中,程序员需要手动 malloc
/free
或 new
/delete
。这给予了他们极致的控制权,但也带来了无尽的麻烦:内存泄漏、二次释放、悬垂指针……
Rust 声称自己既能媲美 C++ 的性能,又能提供高级语言的内存安全。它是怎么做到的?它既没有 GC,也不需要我们手动管理内存。
答案,就是 Rust 的镇山之宝,也是它最核心、最独特的概念:
所有权(Ownership)
所有权是一套规则,它在编译期就检查你对内存的使用是否合法。编译器会像一个极其严格的图书管理员,精确地追踪每一份数据(每一本书)的“所有者”。
- 当一个变量拥有某块数据时,它就是这块数据的“所有者”。
- 一块数据在同一时间只能有一个所有者。
- 当所有者离开其作用域(比如函数执行结束)时,它所拥有的数据会自动被清理。
编译器会在编译代码的时候,就帮你把释放内存的代码(类似 free
)在合适的地方悄悄地插入。这一切都发生在编译期,最终生成的二进制文件里已经包含了所有内存管理逻辑。
这意味着什么?
你获得了 GC 的内存安全(不会忘记释放),同时拥有了手动管理的性能(没有运行时开销)。这就是 Rust 所谓的“零成本抽象(Zero-Cost Abstraction)”。
本章小结
恭喜你!你已经成功迈出了从 Java 到 Rust 的第一步。我们回顾一下今天的旅程:
- 我们明确了学习 Rust 的动机:为了追求极致的性能、安全和并发能力。
- 我们使用
rustup
和cargo
搭建了开发环境,并体会到了cargo
作为项目管理工具的便捷。 - 我们编写并运行了第一个 Rust 程序,并通过与 Java 的对比,了解了 Rust 函数和宏的基本语法。
- 最重要的是,我们提出了那个直击灵魂的问题——“GC 去哪了?”,并引出了 Rust 的核心答案:所有权系统。
现在,潘多拉的魔盒已经被打开了。“所有权”这个概念可能听起来还有些抽象和神秘。别担心,这正是我们接下来要探索的奇妙新世界。
在下一章 《变量与可变性——从 final
到 let
和 mut
的思维转变》 中,我们将通过一个最基础的操作——变量声明,来亲手触摸和感受所有权世界的第一条法则。准备好,真正的冒险,才刚刚开始。