Learning goals
Define and invoke methods with clear signatures, understand pass-by-value semantics, overload methods, use recursion safely, and apply JDK 21 features like var in locals without confusing method design.
Method anatomy
public static int add(int a, int b) {
return a + b;
}
| Part | Meaning |
|---|---|
public |
Callable from anywhere (other modifiers later) |
static |
Belongs to class, not instance |
int |
Return type (void = no return value) |
add |
Method name |
(int a, int b) |
Parameters |
return |
Sends value back to caller |
Invocation:
int sum = add(2, 3);
Instance methods
Non-static methods require an object:
public class Counter {
private int value = 0;
public void increment() {
value++;
}
public int getValue() {
return value;
}
}
Counter c = new Counter();
c.increment();
System.out.println(c.getValue()); // 1
increment implicitly uses this—the current instance.
Pass-by-value
Java always passes copies of values:
static void bump(int x) {
x++;
}
int n = 5;
bump(n);
// n is still 5
For references, the reference copy is passed—both point to the same object:
static void appendExclamation(StringBuilder sb) {
sb.append("!");
}
StringBuilder builder = new StringBuilder("hi");
appendExclamation(builder);
// builder content is "hi!"
You cannot reassign the caller’s variable from inside the method:
static void reassign(StringBuilder sb) {
sb = new StringBuilder("new"); // does not change caller's reference
}
Method overloading
Same name, different parameter lists (type and/or count):
static int max(int a, int b) {
return a > b ? a : b;
}
static double max(double a, double b) {
return a > b ? a : b;
}
static int max(int a, int b, int c) {
return max(max(a, b), c);
}
Return type alone is not enough to overload—signature must differ.
Varargs
static int sum(int... numbers) {
int total = 0;
for (int n : numbers) {
total += n;
}
return total;
}
sum(1, 2, 3); // numbers treated as int[]
Varargs must be the last parameter. Prefer overloads or List when clarity matters.
Recursion
static long factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
Every recursive path needs a base case. Deep recursion can StackOverflowError—iterative or tail-friendly algorithms for large n.
Javadoc and naming
Document public API briefly:
/**
* Returns the absolute difference between two integers.
*/
static int absDiff(int a, int b) {
return Math.abs(a - b);
}
Method names are verbs (calculateTotal, isEmpty). Boolean getters often is/has prefix.
Records and compact methods (JDK 16+)
Records generate constructor, accessors, equals, hashCode, toString:
record Point(int x, int y) {
public Point {
if (x < 0 || y < 0) {
throw new IllegalArgumentException("negative");
}
}
public double distanceFromOrigin() {
return Math.hypot(x, y);
}
}
Compact constructor validates without boilerplate assignment—fields are final.
Common mistakes
- Missing return on non-void path — compile error.
- Unreachable code after
return. - Overloading ambiguity —
print(null)withprint(String)andprint(Object)may fail to compile. - Huge parameter lists — group into a record or parameter object.
- Side effects in getters —
getBalance()should not deduct fees.
Practice checkpoint
-
Write
static boolean isBetween(int x, int min, int max)inclusive.- Answer:
return x >= min && x <= max;
- Answer:
-
After
void reset(String s) { s = ""; }called with"hi", is caller’s variable empty?- Answer: No—reference reassignment is local.
-
Overload
parseforString→intandString→double.- Answer:
Integer.parseInt(s)vsDouble.parseDouble(s).
- Answer:
-
What is factorial(0) with the recursive method above?
- Answer:
1(base case).
- Answer:
Interview angles
- “Is Java pass-by-reference?” — No, pass-by-value always; reference types pass copy of reference.
- “Overload vs override?” — Overload: same class, different params. Override: subclass replaces superclass method (same signature).
- “Static vs instance method?” — Static needs no object; cannot use instance fields directly unless passed in.