Why can you use String, System, and Integer without importing them, and what is special about java.lang?
answer
- java.lang is auto-imported into every file
- It's the ONLY package auto-imported
- Holds Object, String, System, wrappers, Math, Thread, exceptions
- Shallow: subpackages (java.lang.reflect) still need imports
- Your own same-named type shadows it (wildcard import is lowest priority)
basics
~10 sString, 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 sThose 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
Knows core types like String/System come from java.lang and need no import.
States that java.lang is the only auto-imported package and that the import is shallow (subpackages excluded).
Explains the implicit import java.lang.* as an on-demand import, its low resolution priority, and shadowing by user-declared types.
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