books.chapter 5Learn Java in 10 Days

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

  1. Each method should have a single responsibility
  2. Java is always pass-by-value (for references, the reference value is copied)
  3. Overloaded methods are distinguished by parameter types and count
  4. 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.