skip to content

What happens when static imports introduce a naming collision? Walk through the rules for ambiguity and shadowing.

level: seniorimportance: should knowfreq 35%

answer

  1. precedence: local/inherited > explicit import > wildcard
  2. two wildcards, same name = ambiguity compile error
  3. fix: qualify or make it explicit
  4. local member silently shadows the import
  5. overloads are not a clash

basics

~20 s

If two static imports bring in the same simple name and you use it unqualified, the compiler errors as ambiguous and you must qualify the name (write the class). A member in your own class, or an explicit single import, takes priority over a wildcard one and quietly wins.

solid answer

~50 s

Collisions resolve by a precedence chain. A member declared in (or inherited by) the current class beats any import; an explicit single-member static import beats a wildcard static import. So if a name exists both as a local/inherited member and as a static import, the local one wins and the import is effectively shadowed — sometimes silently and surprisingly. The genuinely broken case is two equal-precedence sources: if two wildcard static imports each expose the same simple name and you use it unqualified, the compiler reports an ambiguity error and you must disambiguate by qualifying with the class name or replacing one with an explicit import. A subtle trap: a static import can collide with a same-named member of the enclosing class or even a regular-imported type, and the silent winner may not be the one you intended, which is exactly why explicit imports and avoiding generic names matter.

go deeper

for a junior

Knows that two imports bringing in the same name can cause an error and that qualifying with the class name fixes it.

for a middle

States the precedence chain (local/inherited > explicit > wildcard) and that two wildcards with the same name is a compile error.

for a senior

Distinguishes the silent-shadowing cases from the real ambiguity error, knows overloads are not a clash, and gives concrete fixes and prevention.

for a principal

Anticipates clash-prone designs (generic factory names), sets import conventions and lint rules to prevent silent shadowing surprises across a large codebase.

## The problem A static import lets you use a static member by its **simple name** (no `ClassName.` prefix). But simple names aren't unique across classes — two classes can both have a static method `of` or a constant `EMPTY`. When more than one thing claims the same bare name in a file, Java needs rules to decide what an unqualified use means. ## The precedence chain (highest priority first) When the compiler sees an unqualified name `foo`, it resolves in this order: 1. **A member declared in the current class, or inherited from a supertype.** These always win over imports. 2. **An explicit single-member static import** (`import static X.foo;`). 3. **A wildcard static import** (`import static X.*;`). Lowest priority. A higher source **shadows** (hides) a lower one for that name — and crucially, this can happen **silently**, with no warning. ### Example of silent shadowing ```java import static java.lang.Integer.MAX_VALUE; // wildcard-or-explicit import class C { static final int MAX_VALUE = 5; // member of this class void m() { System.out.println(MAX_VALUE); // prints 5, NOT Integer.MAX_VALUE } } ``` The local field wins per rule 1; the import is hidden. No error — just possibly-surprising behavior. ### Explicit beats wildcard ```java import static java.util.Collections.emptyList; // explicit import static some.other.Util.*; // wildcard also has emptyList // unqualified emptyList() -> the explicit import wins, unambiguously ``` ## The genuine error: equal-precedence ambiguity If two sources at the **same** precedence level both supply the bare name, the compiler can't choose and **fails to compile**. The classic case is two **wildcard** static imports: ```java import static a.A.*; // A has static of(...) import static b.B.*; // B also has static of(...) of(...); // COMPILE ERROR: reference to 'of' is ambiguous ``` Fixes: (a) **qualify** it — `A.of(...)`; or (b) replace one wildcard with an **explicit** import, which raises that name's precedence and breaks the tie. ## Static import vs. a regular-imported type A static import can also collide with a **type** name brought in by a normal import, or with the simple name of the enclosing class. Java's spec resolves these via the name-resolution rules (a member name vs a type name are looked up in different contexts), but the practical lesson is the same: collisions are confusing, and the silent winner may surprise you. ## Overloads are *not* a clash Importing a name that has several overloads (e.g. `Math.max(int,int)` and `Math.max(double,double)`) is **not** an ambiguity — all overloads come in under one name and normal overload resolution picks the right signature at each call. Ambiguity is about the same simple name coming from **different declaring classes** at equal precedence. ## Why this matters / how to avoid it - **Prefer explicit single-member imports** — they're unambiguous and raise precedence, so they win cleanly over wildcards. - **Avoid statically importing generic names** (`of`, `get`, `valueOf`, `create`, `EMPTY`) that many classes share — these are clash magnets. - When a clash does occur, the safe, always-available fix is to **drop the static import for that name and qualify it** with the class. - Be aware of **silent shadowing** by local/inherited members: a static import can be quietly overridden, so don't assume a bare name resolves to the import.

  • Two wildcard static imports both expose a static method named 'of' and you call of(...) unqualified — what happens, and how do you fix it?
    It's a compile error because the reference is ambiguous at equal precedence. Fix it by qualifying the call with the class name (A.of(...)) or by replacing one wildcard with an explicit single-member import, which has higher precedence and breaks the tie.
  • If your class declares a static field with the same name as a statically imported constant, which one does an unqualified use refer to?
    The class's own (or inherited) member wins — it has the highest precedence and silently shadows the import, with no error or warning.

saying these in an interview costs you the question

  • Thinking a name clash always produces a compile error (silent shadowing by local/explicit can occur)
  • Believing wildcard imports outrank explicit imports
  • Treating overloaded methods as an ambiguity
  • Assuming the import always wins over a same-named local field

context