Gotcha roundup II — types & objects
Overload resolution order, var rules, autoboxing NPE, pass-by-value, default-constructor loss, final/static init order, checked vs unchecked.
Traps in how Java resolves types and creates objects
### Overload resolution order
When you call a method with an argument that could match multiple overloads, Java picks the most specific match in this order:
- Exact match — types match exactly.
- Widening — e.g., pass
int, matchlong. - Autoboxing — e.g., pass
int, matchInteger. - Varargs — e.g., pass
int, matchint....
void print(long x) { System.out.println("long"); }
void print(Integer x) { System.out.println("Integer"); }
print(5); // "long" — widening wins over boxing
### var rules
- Only for local variables with an initialiser.
- Not for fields, method parameters, constructor parameters, return types, or catch variables.
- var list = null; is a compile error — the type cannot be inferred from null.
- var is not a keyword; it is a reserved type name.
### Autoboxing NullPointerException
Integer count = null;
int c = count; // NullPointerException at runtime — unboxing null
Unboxing a null wrapper throws NPE. This happens silently in assignments, comparisons (count == 5 unboxes count), and arithmetic. Guard with an explicit null check before any unboxing operation.
### Pass-by-value — always
Java passes everything by value. For primitives, the value is the number. For reference types, the value is the reference (the pointer). Reassigning the parameter does not affect the caller's variable; mutating the object through the reference does:
void change(StringBuilder sb, String s) {
sb.append(" world"); // mutates the object the caller sees
s = "new"; // reassigns local copy only — caller unchanged
}
### Default constructor disappears
The compiler generates a no-arg constructor only when the class defines no constructors at all. The moment you write any constructor, the default disappears:
class Point {
Point(int x, int y) { ... } // you wrote a constructor
}
Point p = new Point(); // compile error — no no-arg constructor
### final and static field initialisation order
Static fields and static initialisers run once in textual order when the class is loaded. Instance fields and instance initialisers run in textual order before the constructor body, each time a constructor runs.
### Checked vs unchecked exceptions
- Checked (must declare or catch): extend Exception but not RuntimeException. Examples: IOException, SQLException.
- Unchecked (no obligation): extend RuntimeException or Error. Examples: NullPointerException, IllegalArgumentException.
- If a method throws a checked exception, it must either throws it or catch it — forgetting either is a compile error.