skip to content

Why can you use String, System, and Integer without importing them, and what is special about java.lang?

level: juniorimportance: should knowfreq 50%

answer

  1. java.lang is auto-imported into every file
  2. It's the ONLY package auto-imported
  3. Holds Object, String, System, wrappers, Math, Thread, exceptions
  4. Shallow: subpackages (java.lang.reflect) still need imports
  5. Your own same-named type shadows it (wildcard import is lowest priority)

basics

~10 s

String, System, Integer and similar core types live in the package java.lang, which Java imports automatically into every file. So you don't write import java.lang.String; — it's always already available.

solid answer

~40 s

Those types live in the `java.lang` package, which the compiler implicitly imports into every source file as if you had written `import java.lang.*;`. `java.lang` holds the most fundamental classes — `Object`, `String`, `System`, the primitive wrappers (`Integer`, `Boolean`, …), `Math`, `Thread`, `Exception`/`RuntimeException`, and so on — that virtually all code needs, so requiring an explicit import would be pure noise. It's the only package auto-imported; everything else (e.g. `java.util.List`, `java.io.File`) needs an explicit import or a fully qualified name. Note auto-import is shallow: only `java.lang` itself, not subpackages like `java.lang.reflect` or `java.lang.annotation`, which you must import. If you declare your own class named `String` in your package, your local type shadows `java.lang.String` within that scope.

go deeper

for a junior

Knows core types like String/System come from java.lang and need no import.

for a middle

States that java.lang is the only auto-imported package and that the import is shallow (subpackages excluded).

for a senior

Explains the implicit import java.lang.* as an on-demand import, its low resolution priority, and shadowing by user-declared types.

for a principal

Discusses naming hygiene (never shadow core types), and how implicit imports interact with code readability, tooling, and module readability requirements.

## The everyday observation You can write `String name = "Bob";`, `System.out.println(...)`, or `Integer.parseInt("5")` without any `import` line, yet for `List` or `File` you must add `import java.util.List;` / `import java.io.File;`. Why the difference? ## The rule The Java compiler automatically imports the package **`java.lang`** into **every** source file, exactly as if each file began with: ```java import java.lang.*; ``` You never type that line — it is implicit. Therefore every public type in `java.lang` is usable by its simple name everywhere. ## What lives in java.lang `java.lang` is the package of the language's most foundational types — the ones essentially every program touches: - `Object` — the root superclass of all classes. - `String`, `StringBuilder`, `CharSequence` — text. - The primitive **wrapper** classes: `Integer`, `Long`, `Double`, `Boolean`, `Character`, `Byte`, `Short`, `Float`. - `System` (with `System.out`/`System.in`), `Math`, `Runtime`. - `Thread`, `Runnable`. - `Throwable`, `Exception`, `RuntimeException`, `Error` and common exceptions like `NullPointerException`. - `Class`, `Enum`, `Comparable`, `Iterable`. Because these are needed pervasively, forcing an explicit import on each would add clutter to virtually every file with zero benefit. So the language designers made `java.lang` the one always-available package. ## It is the ONLY auto-imported package Everything else must be imported explicitly or referenced by fully qualified name. `java.util`, `java.io`, `java.time`, `java.nio` — none are auto-imported. This is a common point of confusion: people assume "java.* is automatic," but only `java.lang` is. ## Auto-import is shallow (no subpackages) Importing a package in Java is **not recursive**: `import java.lang.*;` brings in the types declared directly in `java.lang`, but **not** types in its subpackages such as `java.lang.reflect` (`Method`, `Field`), `java.lang.annotation` (`Retention`), or `java.lang.invoke`. Those still require explicit imports. The implicit `java.lang` import behaves identically: shallow, top level only. ## Shadowing: defining your own conflicting type The implicit import is a *type-import-on-demand* (a wildcard import), which has **lower priority** than a type you declare yourself or a single-type import. So if you create your own class named `String` in your package, references to `String` in that scope resolve to *your* class, not `java.lang.String`. (This is legal but a terrible idea — it confuses every reader.) To reach the JDK one anyway, use its fully qualified name `java.lang.String`. ## Why this design is sound It keeps the language ergonomic: the truly universal vocabulary (objects, strings, numbers, exceptions, system access) is always in scope, while specialized libraries remain explicit so the reader can see exactly which dependencies a file pulls in. ## Summary `String`, `System`, `Integer`, and friends need no import because they live in `java.lang`, the single package the compiler implicitly imports into every file (`import java.lang.*;`). The auto-import is shallow (subpackages excluded) and yields to your own same-named types via normal shadowing rules.

  • Is `java.util` auto-imported too?
    No. Only `java.lang` is auto-imported. `java.util.List`, `java.util.Map`, etc. all require explicit imports or fully qualified names.
  • Does the implicit java.lang import include java.lang.reflect.Method?
    No. Package imports are not recursive, so subpackages like `java.lang.reflect` are excluded; you must import `java.lang.reflect.Method` explicitly.

saying these in an interview costs you the question

  • Thinking all of java.* is auto-imported (only java.lang is)
  • Believing java.lang.reflect or java.lang.annotation are auto-imported
  • Assuming wildcard import is recursive into subpackages
  • Saying you literally must write `import java.lang.*;` yourself

context