Day 5: Methods
What You'll Learn Today
- Defining and calling methods
- Parameters and return values
- Method overloading
- Varargs (variable-length arguments)
- Scope and lifetime
What is a Method?
A method is a reusable block of code that performs a specific task.
public class MethodDemo {
// Method definition
static void greet(String name) {
System.out.println("Hello, " + name + "!");
}
public static void main(String[] args) {
// Method calls
greet("Alice");
greet("Bob");
}
}
flowchart TB
subgraph Method["Anatomy of a Method"]
Modifier["Modifier<br>static"]
Return["Return Type<br>void / int / String"]
Name["Method Name<br>greet"]
Params["Parameters<br>(String name)"]
Body["Body<br>{ ... }"]
end
Modifier --> Return --> Name --> Params --> Body
style Modifier fill:#8b5cf6,color:#fff
style Return fill:#3b82f6,color:#fff
style Name fill:#22c55e,color:#fff
style Params fill:#f59e0b,color:#fff
style Body fill:#ef4444,color:#fff
Method Syntax
modifier returnType methodName(parameterList) {
// body
return value; // Not needed for void
}
Return Values
Methods that Return a Value
static int add(int a, int b) {
return a + b;
}
static double calculateBmi(double height, double weight) {
return weight / (height * height);
}
static boolean isEven(int number) {
return number % 2 == 0;
}
// Usage
int sum = add(3, 5); // 8
double bmi = calculateBmi(1.70, 65.0); // 22.49...
boolean even = isEven(4); // true
void Methods
static void printLine(int length) {
for (int i = 0; i < length; i++) {
System.out.print("-");
}
System.out.println();
}
// Usage
printLine(20); // --------------------
Parameters
Pass by Value
Java passes all arguments by value. For primitive types, a copy of the value is passed.
static void tryChange(int x) {
x = 100; // Does not affect the original variable
}
public static void main(String[] args) {
int num = 10;
tryChange(num);
System.out.println(num); // 10 (unchanged)
}
Reference Type Parameters
For reference types, the value of the reference is passed, so you can modify the object's contents.
static void addElement(int[] array, int index, int value) {
array[index] = value; // Modifies the array contents
}
public static void main(String[] args) {
int[] nums = {1, 2, 3};
addElement(nums, 0, 99);
System.out.println(nums[0]); // 99 (changed)
}
flowchart LR
subgraph Primitive["Primitive Type"]
P1["num = 10"] -->|"Copy"| P2["x = 10"]
P3["num = 10<br>(unchanged)"]
end
subgraph Reference["Reference Type"]
R1["nums -> [1,2,3]"] -->|"Copy of reference"| R2["array -> [1,2,3]"]
R3["nums -> [99,2,3]<br>(changed)"]
end
style Primitive fill:#3b82f6,color:#fff
style Reference fill:#22c55e,color:#fff
Method Overloading
You can define multiple methods with the same name as long as they differ in parameter types or count.
static int add(int a, int b) {
return a + b;
}
static double add(double a, double b) {
return a + b;
}
static int add(int a, int b, int c) {
return a + b + c;
}
// The compiler picks the right method based on the arguments
add(1, 2) // int version
add(1.5, 2.5) // double version
add(1, 2, 3) // three-parameter version
Key point: Overloaded methods are distinguished by their parameter types and count. You cannot overload by return type alone.
Varargs (Variable-Length Arguments)
static int sum(int... numbers) {
int total = 0;
for (int n : numbers) {
total += n;
}
return total;
}
// Usage
sum(1, 2, 3) // 6
sum(1, 2, 3, 4, 5) // 15
sum() // 0
Constraint: A varargs parameter must be the last parameter in the method signature.
// OK
static void log(String tag, String... messages) { }
// Not allowed
// static void log(String... messages, String tag) { }
Scope and Lifetime
public class ScopeDemo {
// Class level (static variable)
static int classVar = 100;
static void method() {
// Method level (local variable)
int localVar = 10;
if (true) {
// Block level
int blockVar = 5;
System.out.println(blockVar); // OK
}
// System.out.println(blockVar); // Error: out of scope
}
}
| Scope | Declared In | Accessible Within |
|---|---|---|
| Class level | Directly inside a class | Entire class |
| Method level | Inside a method | That method |
| Block level | Inside {} |
That block |
Recursion
A method that calls itself.
// Factorial: n! = n * (n-1)!
static long factorial(int n) {
if (n <= 1) {
return 1; // Base case
}
return n * factorial(n - 1); // Recursive call
}
// Usage
factorial(5) // 120 (5 * 4 * 3 * 2 * 1)
flowchart TB
F5["factorial(5)<br>5 * factorial(4)"]
F4["factorial(4)<br>4 * factorial(3)"]
F3["factorial(3)<br>3 * factorial(2)"]
F2["factorial(2)<br>2 * factorial(1)"]
F1["factorial(1)<br>return 1"]
F5 --> F4 --> F3 --> F2 --> F1
style F5 fill:#3b82f6,color:#fff
style F4 fill:#3b82f6,color:#fff
style F3 fill:#3b82f6,color:#fff
style F2 fill:#3b82f6,color:#fff
style F1 fill:#22c55e,color:#fff
Fibonacci Sequence
static int fibonacci(int n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
// fibonacci(6) -> 8 (0, 1, 1, 2, 3, 5, 8)
Caution: Every recursive method must have a base case (termination condition). Without one, you'll get an infinite recursion that ends with a
StackOverflowError.
Practice: Utility Methods
import java.util.Arrays;
public class Utilities {
// Maximum value in an array
static int max(int... numbers) {
int result = numbers[0];
for (int n : numbers) {
if (n > result) result = n;
}
return result;
}
// Average of an array
static double average(int... numbers) {
int sum = 0;
for (int n : numbers) {
sum += n;
}
return (double) sum / numbers.length;
}
// Repeat a string
static String repeat(String str, int count) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < count; i++) {
sb.append(str);
}
return sb.toString();
}
// Palindrome check
static boolean isPalindrome(String str) {
String clean = str.toLowerCase().replaceAll("\\s+", "");
return clean.equals(new StringBuilder(clean).reverse().toString());
}
public static void main(String[] args) {
System.out.println("Max: " + max(3, 7, 1, 9, 4));
System.out.printf("Average: %.2f%n", average(80, 90, 75, 88));
System.out.println(repeat("*", 5));
System.out.println("Palindrome? " + isPalindrome("A man a plan a canal Panama"));
}
}
Summary
| Concept | Description |
|---|---|
| Method | A reusable block of code |
| Return value | Use return to send a value back; void returns nothing |
| Pass by value | Primitives pass a copy; references pass a copy of the reference |
| Overloading | Same method name with different parameter types or count |
| Varargs | int... numbers accepts any number of arguments |
| Recursion | A method that calls itself |
Key Takeaways
- Each method should have a single responsibility
- Java is always pass-by-value (for references, the reference value is copied)
- Overloaded methods are distinguished by parameter types and count
- Every recursive method needs a base case
Exercises
Exercise 1: Basic
Write a method that computes the greatest common divisor (GCD) of two integers using the Euclidean algorithm.
Exercise 2: Applied
Write two methods: one that returns the longest string in an array, and another that returns a new array with all strings reversed.
Exercise 3: Challenge
Using recursion, write a program that solves the Tower of Hanoi puzzle for a given number of disks. Print each move as "Move disk 1 from A to C".
References
Next up: On Day 6, we'll dive into Classes and Objects. This is where you'll begin exploring the heart of Java -- object-oriented programming.