Open src/main.rs and you’ll see this:

fn main() {
    println!("Hello, world!");
}

Familiar? It should be. But there are a few things worth noticing if you’re coming from Java.

No class wrapper

In Java, everything lives inside a class — even main:

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello, world!");
    }
}

In Rust, fn main() is a free function. No class, no public static, no String[] args unless you need it. Less ceremony, more signal.

Semicolons matter — but not like in Java

Rust uses semicolons to turn an expression into a statement. This might sound trivial, but it’s actually meaningful:

fn add(a: i32, b: i32) -> i32 {
    a + b   // no semicolon = this is the return value
}

If you add a semicolon to the last line, the function returns () (nothing) instead of the value. The compiler will tell you immediately.

fn — declaring functions

fn greet(name: &str) {
    println!("Hello, {}!", name);
}

fn main() {
    greet("Java Developer");
}

Parameter types go after the name (name: &str), not before like in Java. Return type comes after ->. You’ll get used to it quickly.

Everything is an expression

This is a core Rust idea. if, match, and blocks all return values. You can write:

let message = if true { "yes" } else { "no" };

No ternary operator needed. The block itself is the value.