Every Java program reaches for `Math` at some point, but the import rules catch newcomers off guard. According to codeunderscored.com, the `Math` class lives in `java.lang`, which is imported implicitly in every Java source file, so you can call `Math.PI` without any import at all. Reach for an explicit import only when you want a tidier syntax or a static import shortcut.
This guide walks through both styles, the trade‑offs, and a few patterns worth knowing before you write your next numeric routine.
Quick take
- `Math` is in `java.lang` and is available without any import.
- Call static members through the class name: `Math.PI`, `Math.max(10, 50)`, `Math.sqrt(729)`.
- A static import lets you drop the `Math.` prefix: `import static java.lang.Math.*;`.
- The class is final; you cannot subclass or override its methods.
- All members are static, so there is never a `Math` instance to create.
Two ways to import
The reference article lays out both styles. The first needs no extra code at all. A line such as `System.out.println(Math.PI);` compiles straight away, because every Java file automatically sees the contents of the `java.lang` package. The class name is the only thing you have to remember; the methods and constants are static, so you do not instantiate anything.
The second style is a static import. At the top of the file, write `import static java.lang.Math.*;` to bring every static member of `Math` into scope. From that point on, `PI` works as a bare identifier and `max(10, 50)` works without the `Math.` prefix. A narrower form, `import static java.lang.Math.PI;`, imports only the constant, which is the safer choice when you only need one symbol.
The classic trade‑off is readability versus brevity. `Math.sqrt(729)` tells the next reader exactly where the method came from. `sqrt(729)` is shorter but ambiguous in a file that also uses a `sqrt` method from a third‑party library.
Why this matters
For our readers, the practical concern is not academic; it shows up in code review. A junior developer who blanket‑imports `java.lang.Math.*` and then writes `log(10)` instead of `Math.log(10)` will confuse every reviewer who reads the code. Static imports are wonderful for narrowly scoped domains (testing, mathematics‑heavy modules) and a maintenance headache when overused.
There is also a performance angle worth flagging. `Math` methods are often intrinsics: the JVM recognises calls to `Math.sin`, `Math.sqrt`, and similar methods and replaces them with native CPU instructions. There is no measurable benefit to caching the result of `Math.PI` in a local constant, even though you will see that pattern in older code; the JIT handles it.
Say you are building a geometry helper
Imagine you are writing a small utility class for computing the area and circumference of a circle. With the implicit style, your code reads `double area = Math.PI * radius * radius;` and `double circumference = 2 * Math.PI * radius;`. It is clear, it is portable, and the next reader sees exactly which class is providing `PI`.
If the file is dedicated to geometry and you import `PI` and `sqrt` statically, the same code becomes `double area = PI * radius * radius;`. It is tidier, but only worth it inside a file that uses these symbols many times. Mix the two styles and the file starts to feel inconsistent.
What to watch next
Bottom line: stick with the `Math.` prefix for most code, and reach for a static import only in narrowly scoped modules where the symbols appear repeatedly. The `java.lang` package is always in scope, so any explicit `import java.lang.Math;` is redundant. Watch for `java.lang.Math` updates in newer JDKs; methods like `Math.clamp` have been added over time, and a quick read of the release notes is worth the ten minutes before you write a hand‑rolled clamp.
Key takeaways
- `java.lang.Math` is always imported implicitly; no explicit import is needed.
- Static imports trade clarity for brevity; use them only in narrowly scoped files.
- `Math` methods are JVM intrinsics; do not bother hand‑rolling micro‑optimisations.
- All `Math` members are static, so there is no constructor and no instance.
- Read JDK release notes for new `Math` methods before writing a hand‑rolled version.
Frequently asked questions
Is `import java.lang.Math;` ever useful?
No. The `java.lang` package is imported automatically in every Java source file, so the line is redundant. Modern IDEs flag it as unnecessary.
Can I override `Math` methods?
No. The class is final and all members are static. If you need a different behaviour, write a helper method that calls `Math` and applies your own logic on top.
Are static imports slow?
No. The bytecode is identical, and the JIT inlines calls regardless of how the symbol was imported. Static imports are a readability choice, not a performance one.
What is the difference between `Math.random()` and `Random`?
`Math.random()` returns a `double` in `[0.0, 1.0)` and is convenient for quick needs. For anything more serious, like seeded randomness or multiple streams, use `java.util.Random` or `ThreadLocalRandom`.