Function overloading gives a class or interface multiple methods with one name and different parameter lists. It can make related operations convenient, but the selected overload may be hard to see when argument types, boxing, or a functional-interface signature supply the deciding context. Treat a short call or method reference as potentially ambiguous to a human reader even when Java resolves it unambiguously. section 2.13 section 8.9
Method references can pass an unintended argument
A method reference is adapted to the target functional interface. `Map.computeIfAbsent` expects a function that receives the missing key, so `StringBuilder::new` binds to `StringBuilder(String)`, not the no-argument constructor. Each new builder therefore starts with its filename. Expand the reference to a lambda and explicitly ignore the key when an empty builder is intended. section 2.13
contents.computeIfAbsent(fileName, s -> new StringBuilder())
The explicit lambda exposes the key parameter and constructs an empty `StringBuilder`, making the intended overload visible. section 2.13
The same risk appears when an API overloads operations by both value type and meaning. `List.remove(Object)` removes a matching element, while `List.remove(int)` removes the element at an index. With `List<Integer>`, `remove(0)` selects the `int` overload, so it always removes index zero rather than an `Integer` value of zero. section 8.9
boolean success = offsets.remove((Integer) 0); #1 assert success : "Element 0 wasn't found";
Casting the literal to `Integer` forces removal by value; assigning the result to `boolean` also makes the intended overload and success condition explicit. section 8.9
Reduce overload-related mistakes with deliberate call-site and API choices:
- Replace a suspicious method reference with a lambda to reveal its parameters and the constructor or method call being made. section 2.13
- Check IDE parameter-name hints for calls whose overloads have different meanings; static analysis may not flag a valid-looking `remove(0)` call. section 8.9
- Make value-removal intent explicit with `(Integer) 0`, and use `remove(Object)`'s boolean result when the value is expected to exist. section 8.9
- When narrowing an established `Object`-accepting API, add a typed overload, deprecate the broad overload, and delegate old calls while clients migrate. section 5.3.1
Use overloads to migrate toward a precise contract
An unconditional cast inside `process(Object)` hides a real requirement: only strings are accepted. Prefer `process(String)`. If existing clients require the broad signature, retain `process(Object)` temporarily as a deprecated delegating overload; callers using non-string arguments then receive a deprecation warning while migration proceeds. Where an overridden interface requires `Object`, validate before casting and provide a useful error instead of relying on a failing cast. section 5.3.1


