Values cross method boundaries
Java variables hold primitive values or reference values. Arguments copy these values into parameters. If two references identify the same mutable object, a mutation through one is visible through the other; replacing one reference does not replace the other. This explains why a method can alter a passed list yet cannot replace the caller variable by assigning its parameter. Draw variables and objects separately when tracing code.
Identity and logical equality
The == operator on references asks about identity; equals can define logical equality. When value equality is implemented, hashCode must obey the same contract. Keys should remain stable after insertion into hashed collections. Strings are immutable, but arrays and lists are not automatically value objects. A record simplifies a value carrier yet does not deep-freeze mutable components or remove the need to validate construction.
Contracts and failure
An interface describes promises about operations, not merely names and parameter types. Document null behavior, ownership of returned mutable objects and exceptions callers can expect. Checked exceptions make a compiler-visible handling obligation; unchecked exceptions can still be part of the public failure contract. Preserve causes when translating failures and avoid swallowing an exception just to return a success-shaped default.
Worked Java example
Illustrative snippet: imports, surrounding types or collaborators may be omitted. Read the assumptions before adapting it.
static void change(List<String> names) {
names.add("Mira");
names = new ArrayList<>();
names.add("Arun");
}
List<String> names = new ArrayList<>();
change(names); // caller’s list contains only "Mira"Walkthrough
The parameter initially holds a copy of the reference to the caller list. add("Mira") mutates that list. The assignment then makes the parameter refer to a different list; it does not change the caller variable. The final add changes only the newly allocated local list. The key distinction is which object each reference identifies at each step.
Practice it yourself
Write two different customer objects with the same ID. Decide when == and equals should return true, then state what hashCode must do.
Check your reasoning
Distinct allocations normally fail reference ==. If customer identity is defined solely by an immutable ID, equals may return true and their hash codes must match. Choose an equality model appropriate to the domain rather than comparing every mutable field automatically.
Recall checklist
- Explain the main invariant or contract without looking.
- Trace the example and test an edge case.
- State time, space, input variables and assumptions where relevant.
- Explain one alternative and when you would choose it.