Share:

Methods

intermediate

Part of Core Java

Theory

A method is a block of code that performs a specific task. Methods are used to organize code into reusable units, making programs easier to read, test, and maintain.

Method Declaration

A method declaration has six components:

public static int add(int a, int b) {
    return a + b;
}
  1. Access modifier: public, private, protected, or default
  2. Optional modifier: static, final, abstract, synchronized
  3. Return type: The data type of the value returned (void if nothing is returned)
  4. Method name: Follows camelCase convention
  5. Parameter list: Input values in parentheses
  6. Method body: The code to execute in curly braces

Calling Methods

Methods are called by their name followed by arguments:

int result = add(5, 3);           // Calling a static method
calculator.multiply(4, 2);        // Calling an instance method
System.out.println("Hello");      // Calling a library method

Pass by Value

Java is pass by value. When you pass a variable to a method, Java creates a copy of the value:

public class PassByValue {
    public static void modify(int x) {
        x = 10;  // Only modifies the local copy
    }
 
    public static void main(String[] args) {
        int a = 5;
        modify(a);
        System.out.println(a);  // Still 5!
    }
}

For objects, the reference is passed by value — you can modify the object's state but not reassign the reference:

public static void changeName(Student s) {
    s.setName("New Name");  // This modifies the original object
}
 
public static void reassign(Student s) {
    s = new Student();  // This only changes the local reference
}

Method Overloading

Overloading allows multiple methods with the same name but different parameters:

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
 
    public int add(int a, int b, int c) {
        return a + b + c;
    }
 
    public double add(double a, double b) {
        return a + b;
    }
}

The compiler determines which method to call based on the number and types of arguments. Return type alone is not sufficient for overloading.

Varargs (Variable Arguments)

Varargs allow a method to accept a variable number of arguments:

public static int sum(int... numbers) {
    int total = 0;
    for (int num : numbers) {
        total += num;
    }
    return total;
}
 
// Usage:
sum(1, 2);           // 3
sum(1, 2, 3, 4, 5); // 15
sum();               // 0

Varargs must be the last parameter in the method signature.

The return Keyword

return exits a method and optionally sends a value back:

public int max(int a, int b) {
    if (a > b) {
        return a;  // Early return
    }
    return b;
}

Methods with a non-void return type must have a return statement on all code paths.

Static Methods

Static methods belong to the class rather than any instance. They cannot access instance variables directly:

public class StringUtils {
    public static boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }
 
    public static String reverse(String str) {
        return new StringBuilder(str).reverse().toString();
    }
}
 
// Called on the class, not an instance
StringUtils.isEmpty("hello");

Method Scope

Variables declared inside a method are local variables — they only exist within that method:

public void calculate() {
    int x = 5;  // Local variable — only accessible within this method
    if (x > 0) {
        int y = 10;  // Block-scoped — only accessible within the if block
        System.out.println(x + y);
    }
    // System.out.println(y);  // Compile error: y is out of scope
}

Recursion

Recursion is when a method calls itself. Every recursive method needs:

  1. A base case that stops the recursion
  2. A recursive call that moves toward the base case
public static int factorial(int n) {
    // Base case
    if (n <= 1) {
        return 1;
    }
    // Recursive case
    return n * factorial(n - 1);
}

Recursion can make code elegant for problems like tree traversal, but may cause StackOverflowError if the recursion depth is too large. Use iteration for simple repetitive tasks.

Practical Examples

Example 1: Method Overloading and Varargs
java
Example 2: Recursive Fibonacci
java

For production code, prefer iteration over recursion when possible. Recursion is best suited for naturally recursive structures like trees, graphs, and divide-and-conquer algorithms.

Exercises

Method Overloading Practice

easy

Create a Printer class with three overloaded print methods: one that prints a String, one that prints an int, and one that prints a String and an int together.

Expected Output:

Hello\n42\nScore: 95

Palindrome Checker with Recursion

medium

Write a recursive method isPalindrome(String str) that returns true if the string is a palindrome (reads the same forwards and backwards), ignoring case and non-alphanumeric characters.

Expected Output:

true\nfalse\ntrue

Varargs Statistics

medium

Write a Stats class with static methods that accept varargs of double values and return the min, max, sum, and average. Handle the case where no arguments are passed.

Expected Output:

Min: 1.7\nMax: 9.1\nSum: 23.1\nAvg: 4.62\nEmpty avg: 0.0

Mini Quiz

Mini Quiz

Mini Project

Mini Project: String Utilities Library

Create a StringUtils utility class with a collection of static methods for string manipulation. Use method overloading, varargs, and recursion where appropriate.

Requirements:

    Bonus Challenge

    Add methods: capitalize(String str) — capitalizes the first letter of each word, and abbreviate(String str, int maxWords) — keeps only the first N words.